home *** CD-ROM | disk | FTP | other *** search
/ CICA 1995 September (Japanese) / CICA Shareware for Windows CD-ROM (Walnut Creek) (September 1995) (Japanese) (Disc 2).iso / disc2 / nt / ntperf.exe / PERFTOOLS / SRC / PERFMON / REPORT.C_ / REPORT.C
Encoding:
C/C++ Source or Header  |  1993-05-15  |  71.7 KB  |  2,607 lines

  1. #include "perfmon.h"
  2. #include <stdio.h>      // for sprintf
  3. #include <string.h>     // for strncpy
  4. #include "report.h"     // Exported declarations for this file
  5.  
  6. #include "addline.h"    // for AddLine, EditLine
  7. #include "perferr.h"    // for PostError
  8. #include "fileutil.h"   // for FileHandleCreate
  9. #include "line.h"       // for LineAppend
  10. #include "pmemory.h"    // for MemoryXXX (mallloc-type) routines
  11. #include "perfdata.h"   // for UpdateLines
  12. #include "perfmops.h"   // for DoWindowDrag
  13. #include "playback.h"   // for PlaybackLines, PlayingBackLog
  14. #include "print.h"      // for PrintDC
  15. #include "system.h"     // for SystemGet
  16. #include "utils.h"
  17. #include "menuids.h"    // for IDM_VIEWREPORT
  18. #include "fileopen.h"   // for FileGetName
  19.  
  20.  
  21. //==========================================================================//
  22. //                                Local Data                                //
  23. //==========================================================================//
  24.  
  25. TCHAR          szSystemFormat [ResourceStringLen] ;
  26. TCHAR          szObjectFormat [ResourceStringLen] ;
  27.  
  28.  
  29.  
  30.  
  31.  
  32. //==========================================================================//
  33. //                                  Constants                               //
  34. //==========================================================================//
  35.  
  36.  
  37. #define xSystemMargin               (xScrollWidth)
  38. #define xObjectMargin               (2 * xScrollWidth)
  39. #define xCounterMargin              (3 * xScrollWidth)
  40. #define xColumnMargin               (xScrollWidth)
  41.  
  42. #define RightHandMargin             xObjectMargin
  43. #define ValueMargin(pReport)       \
  44.    (4 * xScrollWidth + pReport->xMaxCounterWidth)
  45.  
  46.  
  47. //=============================//
  48. // Report Class                //
  49. //=============================//
  50.  
  51.  
  52. TCHAR   szReportWindowClass[] = TEXT("PerfmonReportClass") ;
  53. #define dwReportClassStyle           (CS_HREDRAW | CS_VREDRAW | CS_DBLCLKS)
  54. #define iReportClassExtra            (0)
  55. #define iReportWindowExtra           (0)
  56. #define dwReportWindowStyle          (WS_CHILD | WS_VSCROLL | WS_HSCROLL)
  57.  
  58.  
  59. #define szValuePlaceholder          TEXT("-999999999.999")
  60. #define szLargeValueFormat          TEXT("%12.0f")
  61. #define eStatusLargeValueMax        ((FLOAT) 999999999.0)
  62. #define szValueFormat               TEXT("%12.3f")
  63.  
  64.  
  65. //==========================================================================//
  66. //                              Local Functions                             //
  67. //==========================================================================//
  68.  
  69.  
  70. PREPORT AllocateReportData (HWND hWndReport)
  71.    {
  72.    PREPORT        pReport ;
  73.  
  74.    pReport = ReportData (hWndReport) ;
  75.  
  76.    pReport->hWnd = hWndReport ;
  77.    pReport->iStatus = iPMStatusClosed ;
  78.    pReport->bManualRefresh = FALSE ;
  79.    pReport->bModified = FALSE ;
  80.  
  81.    pReport->Visual.iColorIndex = 0 ;
  82.    pReport->Visual.iWidthIndex = -1 ;
  83.    pReport->Visual.iStyleIndex = -1 ;
  84.  
  85.    pReport->iIntervalMSecs = iDefaultReportIntervalSecs * 1000 ;
  86.    pReport->pSystemFirst = NULL ;
  87.    pReport->pLineFirst = NULL ;
  88.  
  89.    pReport->pLineCurrent = NULL ;
  90.  
  91.    return (pReport) ;
  92.    }  // AllocateReportData
  93.  
  94.  
  95. void FreeReportData (PREPORT pReport)
  96.    {  // FreeReportData
  97.    }  // FreeReportData
  98.  
  99.  
  100.  
  101. BOOL LineCounterRemove (PPLINE ppLineFirst,
  102.                         PLINE pLineRemove)
  103.    {
  104.    PLINE          pLine ;
  105.  
  106.    if (*ppLineFirst == pLineRemove)
  107.       {
  108.       *ppLineFirst = (*ppLineFirst)->pLineCounterNext ;
  109.       return (TRUE) ;
  110.       }
  111.  
  112.    for (pLine = *ppLineFirst ;
  113.         pLine->pLineCounterNext ;
  114.         pLine = pLine->pLineCounterNext)
  115.       {   // for
  116.       if (pLine->pLineCounterNext == pLineRemove)
  117.          {
  118.          pLine->pLineCounterNext = pLineRemove->pLineCounterNext ;
  119.          return (TRUE) ;
  120.          }  // if
  121.       }  // for
  122.  
  123.    return (FALSE) ;
  124.    }  // LineCounterRemove
  125.  
  126.  
  127. //======================================//
  128. // Column Group routines                //
  129. //======================================//
  130.  
  131.  
  132. BOOL ColumnSame (PCOLUMNGROUP pColumnGroup,
  133.                  LPTSTR lpszParentName,
  134.                  LPTSTR lpszInstanceName)
  135.    {  // ColumnSame
  136.    BOOL           bParentSame ;
  137.    BOOL           bInstanceSame ;
  138.  
  139.    bParentSame = (!lpszParentName && !pColumnGroup->lpszParentName) ||
  140.                  strsame (lpszParentName, pColumnGroup->lpszParentName) ;
  141.    bInstanceSame = (!lpszInstanceName && !pColumnGroup->lpszInstanceName) ||
  142.                  strsame (lpszInstanceName, pColumnGroup->lpszInstanceName) ;
  143.  
  144.    return (bParentSame && bInstanceSame) ;                 
  145.    }  // ColumnSame
  146.  
  147.  
  148. PCOLUMNGROUP ColumnGroupCreate (PREPORT pReport,
  149.                                 int xPos,
  150.                                 LPTSTR lpszParentName,
  151.                                 LPTSTR lpszInstanceName,
  152.                                 int PreviousColumnNumber)
  153.    {  // ColumnGroupCreate
  154.    PCOLUMNGROUP   pColumnGroup ;
  155.    HDC            hDC ;
  156.  
  157.    hDC = GetDC (pReport->hWnd) ;
  158.    pColumnGroup = MemoryAllocate (sizeof (COLUMNGROUP)) ;
  159.  
  160.    if (pColumnGroup)
  161.       {
  162.       pColumnGroup->pColumnGroupNext = NULL ;
  163.       pColumnGroup->lpszParentName = StringAllocate (lpszParentName) ;
  164.       pColumnGroup->lpszInstanceName = StringAllocate (lpszInstanceName) ;
  165.       pColumnGroup->ParentNameTextWidth = TextWidth (hDC, lpszParentName) ;
  166.       pColumnGroup->InstanceNameTextWidth = TextWidth (hDC, lpszInstanceName) ;
  167.       pColumnGroup->xPos = xPos ;
  168.       pColumnGroup->ColumnNumber = PreviousColumnNumber + 1 ;
  169.       pColumnGroup->xWidth = max (max (pColumnGroup->ParentNameTextWidth,
  170.                                        pColumnGroup->InstanceNameTextWidth),
  171.                                   pReport->xValueWidth) ;
  172.  
  173.       pReport->xWidth = max (pReport->xWidth,
  174.                              RightHandMargin +
  175.                              ValueMargin (pReport) + 
  176.                              pColumnGroup->xPos + pColumnGroup->xWidth + 
  177.                              xColumnMargin) ;
  178.       }  // if
  179.  
  180.    ReleaseDC (pReport->hWnd, hDC) ;
  181.    return (pColumnGroup) ;
  182.    }  // ColumnGroupCreate
  183.  
  184.  
  185.  
  186. PCOLUMNGROUP ColumnGroup (PREPORT pReport,
  187.                           POBJECTGROUP pObjectGroup,
  188.                           PLINE pLine)
  189. /*
  190.    Effect:        Return a pointer to the appropriate column group from
  191.                   within the groups of pObject. If the line is a counter
  192.                   without instances, return NULL. Otherwise, determine
  193.                   if the counter's parent/instance pair is already found
  194.                   in an existing column and return a pointer to that column.
  195.  
  196.                   If a column with the appropriate parent/instance isn't
  197.                   found, add a new column *at the end*, and return that
  198.                   column.
  199.  
  200.    Note:          This function has multiple return points.
  201. */
  202.    {  // ColumnGroup
  203.    PCOLUMNGROUP   pColumnGroup ;
  204.    LPTSTR         lpszParentName ;
  205.    LPTSTR         lpszInstanceName ;
  206.  
  207.  
  208.    if (!LineInstanceName (pLine))
  209.       return (NULL) ;
  210.  
  211.  
  212.    lpszParentName = LineParentName (pLine) ;
  213.    lpszInstanceName = LineInstanceName (pLine) ;
  214.       
  215.    if (!pObjectGroup->pColumnGroupFirst)
  216.       {
  217.       pObjectGroup->pColumnGroupFirst = 
  218.          ColumnGroupCreate (pReport, 0, lpszParentName, lpszInstanceName, -1) ;
  219.       return (pObjectGroup->pColumnGroupFirst) ;
  220.       }
  221.  
  222.    for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  223.         pColumnGroup ;
  224.         pColumnGroup = pColumnGroup->pColumnGroupNext)
  225.       {  // for
  226.       if (ColumnSame (pColumnGroup, lpszParentName, lpszInstanceName))
  227.          return (pColumnGroup) ;
  228.  
  229.       else if (!pColumnGroup->pColumnGroupNext)
  230.          {  // if
  231.          pColumnGroup->pColumnGroupNext = 
  232.             ColumnGroupCreate (pReport,
  233.                                pColumnGroup->xPos + pColumnGroup->xWidth +
  234.                                xColumnMargin,
  235.                                lpszParentName,
  236.                                lpszInstanceName,
  237.                                pColumnGroup->ColumnNumber) ;
  238.          return (pColumnGroup->pColumnGroupNext) ;
  239.          }  // if
  240.       }  // for
  241.  
  242.    return (NULL) ;
  243.    }  // ColumnGroup
  244.  
  245.  
  246.  
  247. //======================================//
  248. // Counter Group routines               //
  249. //======================================//
  250.  
  251.  
  252. PCOUNTERGROUP CounterGroupCreate (DWORD dwCounterIndex)
  253.    {  // CounterGroupCreate
  254.    PCOUNTERGROUP   pCounterGroup ;
  255.  
  256.    pCounterGroup = MemoryAllocate (sizeof (COUNTERGROUP)) ;
  257.  
  258.    if (pCounterGroup)
  259.       {
  260.       pCounterGroup->pCounterGroupNext = NULL ;
  261.       pCounterGroup->pLineFirst = NULL ;
  262.       pCounterGroup->dwCounterIndex = dwCounterIndex ;
  263.       }  // if
  264.  
  265.    return (pCounterGroup) ;
  266.    }  // CounterGroupCreate
  267.  
  268.  
  269. PCOUNTERGROUP CounterGroup (POBJECTGROUP pObjectGroup,
  270.                             DWORD dwCounterIndex,
  271.                             BOOL *pbCounterGroupCreated) 
  272.    {  // CounterGroup
  273.    PCOUNTERGROUP   pCounterGroup ;
  274.  
  275.    *pbCounterGroupCreated = FALSE ;
  276.    if (!pObjectGroup)
  277.       return (FALSE) ;
  278.  
  279.    if (!pObjectGroup->pCounterGroupFirst)
  280.       {
  281.       pObjectGroup->pCounterGroupFirst = CounterGroupCreate (dwCounterIndex) ;
  282.       *pbCounterGroupCreated = TRUE ;
  283.       return (pObjectGroup->pCounterGroupFirst) ;
  284.       }
  285.  
  286.    for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  287.         pCounterGroup ;
  288.         pCounterGroup = pCounterGroup->pCounterGroupNext)
  289.       {  // for
  290.       if (pCounterGroup->dwCounterIndex == dwCounterIndex)
  291.          return (pCounterGroup) ;
  292.       else if (!pCounterGroup->pCounterGroupNext)
  293.          {  // if
  294.          pCounterGroup->pCounterGroupNext = 
  295.             CounterGroupCreate (dwCounterIndex) ;
  296.          *pbCounterGroupCreated = TRUE ;
  297.          return (pCounterGroup->pCounterGroupNext) ;
  298.          }  // if
  299.       }  // for
  300.  
  301.    return (NULL) ;
  302.    }  // CounterGroup
  303.  
  304.  
  305. //======================================//
  306. // Object Group routines                //
  307. //======================================//
  308.  
  309.  
  310. POBJECTGROUP ObjectGroupCreate (LPTSTR lpszObjectName)
  311.    {  // ObjectGroupCreate
  312.    POBJECTGROUP   pObjectGroup ;
  313.    HDC            hDC ;
  314.    PREPORT        pReport ;
  315.    int            OldCounterWidth ;
  316.  
  317.    pObjectGroup = MemoryAllocate (sizeof (OBJECTGROUP)) ;
  318.  
  319.    if (pObjectGroup)
  320.       {
  321.       pObjectGroup->pObjectGroupNext = NULL ;
  322.       pObjectGroup->pCounterGroupFirst = NULL ;
  323.       pObjectGroup->pColumnGroupFirst = NULL ;
  324.       pObjectGroup->lpszObjectName = StringAllocate (lpszObjectName) ;
  325.  
  326.       hDC = GetDC (hWndReport) ;
  327.       pReport = ReportData (hWndReport) ;
  328.       SelectFont (hDC, pReport->hFontHeaders) ;
  329.  
  330.       // re-calc. the max. counter group width
  331.       OldCounterWidth = pReport->xMaxCounterWidth ;
  332.       pReport->xMaxCounterWidth =
  333.             max (pReport->xMaxCounterWidth,
  334.                  TextWidth (hDC, lpszObjectName) + xObjectMargin) ;
  335.  
  336.       if (OldCounterWidth < pReport->xMaxCounterWidth)
  337.           {
  338.           // adjust the report width with the new counter width
  339.           pReport->xWidth +=
  340.                (pReport->xMaxCounterWidth - OldCounterWidth);
  341.           }
  342.  
  343.       ReleaseDC (hWndReport, hDC) ;
  344.       }  // if
  345.    return (pObjectGroup) ;
  346.    }  // ObjectGroupCreate
  347.  
  348.  
  349. POBJECTGROUP ObjectGroup (PSYSTEMGROUP pSystemGroup,
  350.                           LPTSTR lpszObjectName)
  351.    {
  352.    POBJECTGROUP   pObjectGroup ;
  353.  
  354.    if (!pSystemGroup)
  355.       return (FALSE) ;
  356.  
  357.    if (!pSystemGroup->pObjectGroupFirst)
  358.       {
  359.       pSystemGroup->pObjectGroupFirst = ObjectGroupCreate (lpszObjectName) ;
  360.       return (pSystemGroup->pObjectGroupFirst) ;
  361.       }
  362.  
  363.    for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  364.         pObjectGroup ;
  365.         pObjectGroup = pObjectGroup->pObjectGroupNext)
  366.       {  // for
  367.       if (strsame (pObjectGroup->lpszObjectName, lpszObjectName))
  368.          {
  369.          return (pObjectGroup) ;
  370.          }
  371.       else if (!pObjectGroup->pObjectGroupNext)
  372.          {  // if
  373.          pObjectGroup->pObjectGroupNext = 
  374.             ObjectGroupCreate (lpszObjectName) ;
  375.          return (pObjectGroup->pObjectGroupNext) ;
  376.          }  // if
  377.       }  // for
  378.  
  379.    }  // ObjectGroup
  380.  
  381.  
  382. //======================================//
  383. // System Group routines                //
  384. //======================================//
  385.  
  386.  
  387. PSYSTEMGROUP SystemGroupCreate (LPTSTR lpszSystemName)
  388.    {  // SystemGroupCreate
  389.    PSYSTEMGROUP   pSystemGroup ;
  390.  
  391.    pSystemGroup = MemoryAllocate (sizeof (SYSTEMGROUP)) ;
  392.  
  393.    if (pSystemGroup)
  394.       {
  395.       pSystemGroup->pSystemGroupNext = NULL ;
  396.       pSystemGroup->pObjectGroupFirst = NULL ;
  397.       pSystemGroup->lpszSystemName = StringAllocate (lpszSystemName) ;
  398.       }  // if
  399.  
  400.    return (pSystemGroup) ;
  401.    }  // SystemGroupCreate
  402.  
  403.  
  404. PSYSTEMGROUP SystemGroup (PREPORT pReport,
  405.                           LPTSTR lpszSystemName)
  406. /*
  407.    Effect;        Return a pointer to the system group of pReport with
  408.                   a system name of lpszSystemName. If no system group
  409.                   has that name, add a new system group.
  410. */
  411.    {  // SystemGroup
  412.    PSYSTEMGROUP   pSystemGroup ;
  413.  
  414.    if (!pReport->pSystemGroupFirst)
  415.       {
  416.       pReport->pSystemGroupFirst = SystemGroupCreate (lpszSystemName) ;
  417.       return (pReport->pSystemGroupFirst) ;
  418.       }
  419.  
  420.    for (pSystemGroup = pReport->pSystemGroupFirst ;
  421.         pSystemGroup ;
  422.         pSystemGroup = pSystemGroup->pSystemGroupNext)
  423.       {  // for
  424.       if (strsamei (pSystemGroup->lpszSystemName, lpszSystemName))
  425.          return (pSystemGroup) ;
  426.       else if (!pSystemGroup->pSystemGroupNext)
  427.          {  // if
  428.          pSystemGroup->pSystemGroupNext = 
  429.             SystemGroupCreate (lpszSystemName) ;
  430.          return (pSystemGroup->pSystemGroupNext) ;
  431.          }  // if
  432.       }  // for
  433.    }  // SystemGroup
  434.  
  435.  
  436.  
  437. void DrawCounter (HDC hDC, PREPORT pReport,
  438.                   PCOUNTERGROUP pCounterGroup)
  439.    {  // DrawCounter
  440.  
  441.  
  442.    if (!pCounterGroup->pLineFirst)
  443.       return ;
  444.  
  445.    SelectFont (hDC, pReport->hFont) ;
  446.    TextOut (hDC, xCounterMargin, pCounterGroup->yLine,
  447.             pCounterGroup->pLineFirst->lnCounterName,
  448.             lstrlen (pCounterGroup->pLineFirst->lnCounterName)) ;
  449.    }  // DrawCounter
  450.  
  451.  
  452. void DrawObject (HDC hDC, PREPORT pReport,
  453.                  POBJECTGROUP pObjectGroup)
  454.    {  // DrawObject
  455.    TCHAR          szLine [LongTextLen] ;
  456.    PCOUNTERGROUP  pCounterGroup ;
  457.    PCOLUMNGROUP   pColumnGroup ;
  458.  
  459.    if (!pObjectGroup->pCounterGroupFirst)
  460.       {
  461.       return ;
  462.       }
  463.  
  464.    SelectFont (hDC, pReport->hFontHeaders) ;
  465.  
  466.    SetTextAlign (hDC, TA_RIGHT) ;
  467.  
  468.    for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  469.         pColumnGroup ;
  470.         pColumnGroup = pColumnGroup->pColumnGroupNext)
  471.       {  // for
  472.       // Draw Parent
  473.       if (pColumnGroup->lpszParentName)
  474.          TextOut (hDC, 
  475.                   ValueMargin (pReport) + 
  476.                   pColumnGroup->xPos + pColumnGroup->xWidth,
  477.                   pObjectGroup->yFirstLine - pReport->yLineHeight,
  478.                   pColumnGroup->lpszParentName,
  479.                   lstrlen (pColumnGroup->lpszParentName)) ;
  480.  
  481.       // Draw Instance
  482.       if (pColumnGroup->lpszInstanceName)
  483.          TextOut (hDC, 
  484.                   ValueMargin (pReport) + 
  485.                   pColumnGroup->xPos + pColumnGroup->xWidth,
  486.                   pObjectGroup->yFirstLine,
  487.                   pColumnGroup->lpszInstanceName,
  488.                   lstrlen (pColumnGroup->lpszInstanceName)) ;
  489.       }  // for
  490.    SetTextAlign (hDC, TA_LEFT) ;
  491.  
  492.    TSPRINTF (szLine, szObjectFormat, pObjectGroup->lpszObjectName) ;
  493.    TextOut (hDC, 
  494.             xObjectMargin, pObjectGroup->yFirstLine,
  495.             szLine, lstrlen (szLine)) ;
  496.  
  497.    SelectFont (hDC, pReport->hFont) ;
  498.  
  499.    for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  500.         pCounterGroup ;
  501.         pCounterGroup = pCounterGroup->pCounterGroupNext)
  502.       {  // for
  503.       DrawCounter (hDC, pReport, pCounterGroup) ;
  504.       }  // for
  505.  
  506.    }  // DrawObject
  507.  
  508.  
  509. void DrawSystem (HDC hDC, PREPORT pReport, PSYSTEMGROUP pSystemGroup)
  510.    {  // DrawSystem
  511.    TCHAR          szLine [LongTextLen] ;
  512.    POBJECTGROUP   pObjectGroup ;
  513.  
  514.    SelectFont (hDC, pReport->hFontHeaders) ;
  515.  
  516.    if (!pSystemGroup->pObjectGroupFirst)
  517.       return ;
  518.  
  519.    SetTextAlign (hDC, TA_LEFT) ;
  520.    TSPRINTF (szLine, szSystemFormat, pSystemGroup->lpszSystemName) ;
  521.    TextOut (hDC, 
  522.             xSystemMargin, pSystemGroup->yFirstLine,
  523.             szLine, lstrlen (szLine)) ;
  524.  
  525.    for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  526.         pObjectGroup ;
  527.         pObjectGroup = pObjectGroup->pObjectGroupNext)
  528.       {  // for
  529.       DrawObject (hDC, pReport, pObjectGroup) ;
  530.       }  // for
  531.    }  // DrawSystem
  532.  
  533.  
  534. void ReportValueRect (PREPORT pReport,
  535.                       PLINE pLine,
  536.                       LPRECT lpRect)
  537.    {  // ReportValueRect
  538.    lpRect->left = ValueMargin (pReport) + pLine->xReportPos ;
  539.    lpRect->top = pLine->yReportPos ;
  540.    lpRect->right = lpRect->left + pReport->xValueWidth ;
  541.    lpRect->bottom = lpRect->top + pReport->yLineHeight ;
  542.    }  // ReportValueRect
  543.  
  544.  
  545. void DrawReportValue (HDC hDC, PREPORT pReport, PLINE pLine)
  546.    {  // DrawReportValue
  547.    TCHAR          szValue [20] ;
  548.    FLOAT          eValue ;
  549.    RECT           rectValue ;
  550.  
  551.    // skip until we have collect enough samples for the first data
  552.    if (pLine->bFirstTime == 0)
  553.       {
  554.       eValue = (*(pLine->valNext)) (pLine) ;
  555.       TSPRINTF (szValue,
  556.                 (eValue > eStatusLargeValueMax) ?
  557.                     szLargeValueFormat : szValueFormat,
  558.                 eValue) ;
  559.       }
  560.    else
  561.       {
  562.       // draw "- - - -"
  563.       lstrcpy(szValue, TEXT("- - - -"));
  564.       }
  565.  
  566.    ReportValueRect (pReport, pLine, &rectValue) ;
  567.    
  568.    ExtTextOut (hDC, 
  569.                rectValue.right - 2, rectValue.top,
  570.                ETO_CLIPPED | ETO_OPAQUE,
  571.                &rectValue,
  572.                szValue, lstrlen (szValue), NULL) ;
  573.  
  574.    if (pLine == pReport->pLineCurrent)
  575.       {
  576.       DrawFocusRect (hDC, &rectValue) ;
  577.       }
  578.    }  // DrawReportValue
  579.  
  580.  
  581. void DrawReportValues (HDC hDC, PREPORT pReport)
  582.    {
  583.    PSYSTEMGROUP   pSystemGroup ;
  584.    POBJECTGROUP   pObjectGroup ;
  585.    PCOUNTERGROUP  pCounterGroup ;
  586.    PLINE          pLine ;
  587.  
  588.    SelectFont (hDC, pReport->hFont) ;
  589.    SetTextAlign (hDC, TA_RIGHT) ;
  590.  
  591.    for (pSystemGroup = pReport->pSystemGroupFirst ;
  592.         pSystemGroup ;
  593.         pSystemGroup = pSystemGroup->pSystemGroupNext)
  594.       {  // for System...
  595.       for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  596.            pObjectGroup ;
  597.            pObjectGroup = pObjectGroup->pObjectGroupNext)
  598.          {  // for Object...
  599.          for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  600.               pCounterGroup ;
  601.               pCounterGroup = pCounterGroup->pCounterGroupNext)
  602.             {  // for Counter...
  603.             for (pLine = pCounterGroup->pLineFirst ;
  604.                  pLine ;
  605.                  pLine = pLine->pLineCounterNext)
  606.                {  // for Line...
  607.                DrawReportValue (hDC, pReport, pLine) ;
  608.                }  // for Line...
  609.             }  // for Counter...
  610.          }  // for Object      
  611.       }  // for System...
  612.  
  613.    }
  614.  
  615.  
  616. void DrawReportHeaders (HDC hDC, PREPORT pReport)
  617.    {  // DrawReportHeaders
  618.    PSYSTEMGROUP   pSystemGroup ;
  619.  
  620.    for (pSystemGroup = pReport->pSystemGroupFirst ;
  621.         pSystemGroup ;
  622.         pSystemGroup = pSystemGroup->pSystemGroupNext)
  623.       {  // for
  624.       DrawSystem (hDC, pReport, pSystemGroup) ;
  625.       }  // for         
  626.    }  // DrawReportHeaders
  627.  
  628.  
  629. void DrawReport (HDC hDC, PREPORT pReport)
  630.    {
  631.    SetBkColor (hDC, GetSysColor(COLOR_WINDOW)) ;
  632.    DrawReportHeaders (hDC, pReport) ;
  633.    //UpdateLines (&(pReport->pSystemFirst), pReport->pLineFirst) ;
  634.    DrawReportValues (hDC, pReport) ;
  635.    }
  636.  
  637.  
  638.  
  639. void SetLinePosition (HDC hDC,
  640.                       PREPORT pReport, 
  641.                       POBJECTGROUP pObjectGroup,
  642.                       PLINE pLine)
  643.    {  // SetLinePositions
  644.    PCOLUMNGROUP   pColumnGroup ;
  645.  
  646.  
  647.    pColumnGroup = ColumnGroup (pReport, pObjectGroup, pLine) ;
  648.    if (!pColumnGroup)
  649.       {
  650.       pLine->xReportPos = 0 ;
  651.       pLine->iScaleIndex = -1 ;
  652.       }
  653.    else
  654.       {
  655.       pLine->xReportPos = pColumnGroup->xPos ;
  656.       pLine->iScaleIndex = pColumnGroup->ColumnNumber ;
  657.       }
  658.    }  // SetLinePosition
  659.  
  660.  
  661. void SetCounterPositions (HDC hDC,
  662.                           PREPORT pReport,
  663.                           POBJECTGROUP pObjectGroup,
  664.                           PCOUNTERGROUP pCounterGroup,
  665.                           int yLine)
  666.    {  // SetCounterPositions
  667.    PLINE          pLine ;
  668.    int            yPos ;
  669.  
  670.  
  671.    if (!pCounterGroup->pLineFirst)
  672.       return ;
  673.  
  674.    yPos = pCounterGroup->yLine ;
  675.  
  676.    SelectFont (hDC, pReport->hFontHeaders) ;
  677.  
  678.    for (pLine = pCounterGroup->pLineFirst ;
  679.         pLine ;
  680.         pLine = pLine->pLineCounterNext)
  681.       {  // for
  682.       SetLinePosition (hDC, pReport, pObjectGroup, pLine) ;
  683.       pLine->yReportPos = yPos ;
  684.       }  // for
  685.    }  // SetCounterPositions
  686.  
  687.  
  688. void SetColumnPositions (HDC hDC,
  689.                          PREPORT pReport,
  690.                          POBJECTGROUP pObjectGroup)
  691.    {  // SetColumnPositions
  692.    int            xPos ;
  693.    PCOLUMNGROUP   pColumnGroup ;
  694.  
  695.    xPos = 0 ;
  696.    for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  697.         pColumnGroup ;
  698.         pColumnGroup = pColumnGroup->pColumnGroupNext)
  699.       {  // for
  700.       pColumnGroup->xWidth = max (max (pColumnGroup->ParentNameTextWidth,
  701.                                        pColumnGroup->InstanceNameTextWidth),
  702.                                   pReport->xValueWidth) ;
  703.       pColumnGroup->xPos = xPos ;
  704.       xPos += (pColumnGroup->xWidth + xColumnMargin) ;
  705.       }  // for
  706.    }  // SetColumnPositions
  707.  
  708.  
  709. void SetObjectPositions (HDC hDC,
  710.                          PREPORT pReport,
  711.                          POBJECTGROUP pObjectGroup,
  712.                          int yLine)
  713. /*
  714.    Effect:        Determine and set the logical coordinates for the
  715.                   object pObject within the report pReport.
  716.  
  717.                   For each instance x counter, determine the appropriate
  718.                   column, adding a column description to the object if
  719.                   needed.
  720.  
  721.    Called By:     SetSystemPositions only.
  722.  
  723.    See Also:      SetSystemPositions, SetCounterPositions, ColumnGroup.
  724. */
  725.    {  // SetObjectPositions
  726.    PCOUNTERGROUP  pCounterGroup ;
  727.    int            yPos ;
  728.  
  729.    yPos = pObjectGroup->yFirstLine + yLine ;
  730.  
  731.    SetColumnPositions (hDC, pReport, pObjectGroup) ;
  732.  
  733.    for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  734.         pCounterGroup ;
  735.         pCounterGroup = pCounterGroup->pCounterGroupNext)
  736.       {  // for
  737.       pCounterGroup->yLine = yPos + yLine ;
  738.    
  739.       SetCounterPositions (hDC, pReport, pObjectGroup, pCounterGroup, yLine) ;
  740.  
  741.       yPos = pCounterGroup->yLine ;
  742.       }  // for
  743.  
  744.    pObjectGroup->yLastLine = yPos + yLine ;
  745.    }  // SetObjectPositions
  746.  
  747.  
  748. void SetSystemPositions (HDC hDC,
  749.                          PREPORT pReport, 
  750.                          PSYSTEMGROUP pSystemGroup,
  751.                          int yLine)
  752.    {  // SetSystemPositions
  753.    POBJECTGROUP  pObjectGroup ;
  754.    int            yPos ;
  755.  
  756.    yPos = pSystemGroup->yFirstLine ;
  757.  
  758.    for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  759.         pObjectGroup ;
  760.         pObjectGroup = pObjectGroup->pObjectGroupNext)
  761.       {  // for
  762.       pObjectGroup->yFirstLine = yPos + yLine ;
  763.    
  764.       SetObjectPositions (hDC, pReport, pObjectGroup, yLine) ;
  765.  
  766.       yPos = pObjectGroup->yLastLine ;
  767.       }  // for
  768.  
  769.    pSystemGroup->yLastLine = yPos + yLine ;
  770.    }  // SetSystemPositions
  771.  
  772.  
  773. void static SetScrollRanges (HWND hWnd)
  774.    {  // SetScrollRanges
  775.    PREPORT        pReport ;
  776.    RECT           rectClient ;
  777.    int            xWidth, yHeight ;
  778.  
  779.    GetClientRect (hWnd, &rectClient) ;
  780.    xWidth = rectClient.right - rectClient.left ;
  781.    yHeight = rectClient.bottom - rectClient.top ;
  782.  
  783.    pReport = ReportData (hWnd) ;
  784.  
  785.    SetScrollRange (hWnd, SB_VERT, 
  786.                    0, max (0, pReport->yHeight - yHeight), 
  787.                    TRUE) ;
  788.    SetScrollRange (hWnd, SB_HORZ,
  789.                    0, max (0, pReport->xWidth - xWidth),
  790.                    TRUE) ;
  791.    }  // SetScrollRanges
  792.  
  793.  
  794. BOOL SystemGroupRemove (PSYSTEMGROUP *ppSystemGroupFirst,
  795.                         PSYSTEMGROUP pSystemGroupRemove)
  796.    {
  797.    PSYSTEMGROUP  pSystemGroup ;
  798.  
  799.    if (*ppSystemGroupFirst == pSystemGroupRemove)
  800.       {
  801.       *ppSystemGroupFirst = (*ppSystemGroupFirst)->pSystemGroupNext ;
  802.       MemoryFree (pSystemGroupRemove->lpszSystemName) ;
  803.       MemoryFree (pSystemGroupRemove) ;
  804.       return (TRUE) ;
  805.       }
  806.  
  807.    for (pSystemGroup = *ppSystemGroupFirst ;
  808.         pSystemGroup->pSystemGroupNext ;
  809.         pSystemGroup = pSystemGroup->pSystemGroupNext)
  810.       {   // for
  811.       if (pSystemGroup->pSystemGroupNext == pSystemGroupRemove)
  812.          {
  813.          pSystemGroup->pSystemGroupNext = pSystemGroupRemove->pSystemGroupNext ;
  814.          MemoryFree (pSystemGroupRemove->lpszSystemName) ;
  815.          MemoryFree (pSystemGroupRemove) ;
  816.          return (TRUE) ;
  817.          }  // if
  818.       }  // for
  819.  
  820.    return (FALSE) ;
  821.    }
  822.  
  823. void ColumnGroupRemove (PCOLUMNGROUP pColumnGroupFirst)
  824.    {
  825.    PCOLUMNGROUP   pColumnGroup ;
  826.    PCOLUMNGROUP   pNextColumnGroup ;
  827.  
  828.    for (pColumnGroup = pColumnGroupFirst ;
  829.         pColumnGroup ;
  830.         pColumnGroup = pNextColumnGroup)
  831.       {
  832.       pNextColumnGroup = pColumnGroup->pColumnGroupNext ;
  833.  
  834.       // free memory for this column group
  835.       MemoryFree (pColumnGroup->lpszParentName) ;
  836.       MemoryFree (pColumnGroup->lpszInstanceName) ;
  837.       MemoryFree (pColumnGroup) ;
  838.       }
  839.    }  // ColumnGroupRemove
  840.  
  841. BOOL ObjectGroupRemove (POBJECTGROUP *ppObjectGroupFirst,
  842.                         POBJECTGROUP pObjectGroupRemove)
  843.    {
  844.    POBJECTGROUP  pObjectGroup ;
  845.  
  846.    if (*ppObjectGroupFirst == pObjectGroupRemove)
  847.       {
  848.       *ppObjectGroupFirst = (*ppObjectGroupFirst)->pObjectGroupNext ;
  849.  
  850.       // clean up the allocated memory
  851.       ColumnGroupRemove (pObjectGroupRemove->pColumnGroupFirst) ;
  852.       MemoryFree (pObjectGroupRemove->lpszObjectName) ;
  853.       MemoryFree (pObjectGroupRemove) ;
  854.       return (TRUE) ;
  855.       }
  856.  
  857.    for (pObjectGroup = *ppObjectGroupFirst ;
  858.         pObjectGroup->pObjectGroupNext ;
  859.         pObjectGroup = pObjectGroup->pObjectGroupNext)
  860.       {   // for
  861.       if (pObjectGroup->pObjectGroupNext == pObjectGroupRemove)
  862.          {
  863.          pObjectGroup->pObjectGroupNext = pObjectGroupRemove->pObjectGroupNext ;
  864.  
  865.          // clean up the allocated memory
  866.          ColumnGroupRemove (pObjectGroupRemove->pColumnGroupFirst) ;
  867.          MemoryFree (pObjectGroupRemove->lpszObjectName) ;
  868.          MemoryFree (pObjectGroupRemove) ;
  869.          return (TRUE) ;
  870.          }  // if
  871.       }  // for
  872.  
  873.    return (FALSE) ;
  874.    }
  875.  
  876.  
  877. BOOL CounterGroupRemove (PCOUNTERGROUP *ppCounterGroupFirst,
  878.                         PCOUNTERGROUP pCounterGroupRemove)
  879.    {
  880.    PCOUNTERGROUP  pCounterGroup ;
  881.  
  882.    if (*ppCounterGroupFirst == pCounterGroupRemove)
  883.       {
  884.       *ppCounterGroupFirst = (*ppCounterGroupFirst)->pCounterGroupNext ;
  885.       MemoryFree (pCounterGroupRemove) ;
  886.       return (TRUE) ;
  887.       }
  888.  
  889.    for (pCounterGroup = *ppCounterGroupFirst ;
  890.         pCounterGroup->pCounterGroupNext ;
  891.         pCounterGroup = pCounterGroup->pCounterGroupNext)
  892.       {   // for
  893.       if (pCounterGroup->pCounterGroupNext == pCounterGroupRemove)
  894.          {
  895.          pCounterGroup->pCounterGroupNext = pCounterGroupRemove->pCounterGroupNext ;
  896.          MemoryFree (pCounterGroupRemove) ;
  897.          return (TRUE) ;
  898.          }  // if
  899.       }  // for
  900.  
  901.    return (FALSE) ;
  902.    }
  903.                         
  904.  
  905. //==========================================================================//
  906. //                              Message Handlers                            //
  907. //==========================================================================//
  908.  
  909.  
  910. void static OnCreate (HWND hWnd)
  911.    {  // OnCreate
  912.    HDC            hDC ;
  913.    PREPORT        pReport ;
  914.  
  915.    pReport = AllocateReportData (hWnd) ;
  916.    if (!pReport)
  917.       return ;
  918.  
  919.    pReport->hFont = hFontScales ;
  920.    pReport->hFontHeaders = hFontScalesBold ;
  921.  
  922.    pReport->pLineFirst = NULL ;
  923.    pReport->pSystemFirst = NULL ;
  924.  
  925.    pReport->pSystemGroupFirst = NULL ;
  926.  
  927.    hDC = GetDC (hWnd) ;
  928.  
  929.    SelectFont (hDC, pReport->hFont) ;
  930.  
  931.  
  932.    pReport->yLineHeight = FontHeight (hDC, TRUE) ;
  933.    pReport->xValueWidth = TextWidth (hDC, szValuePlaceholder) ;
  934.    ReleaseDC (hWnd, hDC) ;
  935.  
  936.    pReport->xWidth = 0 ;
  937.    pReport->yHeight = 0 ;
  938.  
  939.    StringLoad (IDS_SYSTEMFORMAT, szSystemFormat) ;
  940.    StringLoad (IDS_OBJECTFORMAT, szObjectFormat) ;
  941.    }  // OnCreate
  942.  
  943.  
  944. void static OnPaint (HWND hWnd)
  945.    {
  946.    HDC            hDC ;
  947.    PAINTSTRUCT    ps ;
  948.    PREPORT        pReport ;
  949.  
  950.  
  951.  
  952.    pReport = ReportData (hWnd) ;
  953.  
  954.    hDC = BeginPaint (hWnd, &ps) ;
  955.    //hDC = hReportDC ;
  956.    SetWindowOrgEx (hDC, 
  957.                    GetScrollPos (hWnd, SB_HORZ), 
  958.                    GetScrollPos (hWnd, SB_VERT),
  959.                    NULL) ;
  960.  
  961.    DrawReport (hDC, pReport) ;
  962.  
  963.    EndPaint (hWnd, &ps) ;
  964.    }
  965.  
  966.  
  967. void static UpdateReportValues (PREPORT pReport)
  968. /*
  969.    Effect:        Redraw all the visible report values of pReport.
  970.                   Since drawing the values completely covers any 
  971.                   previous values, there is no need to erase (or flicker)
  972.                   between updating values.
  973.  
  974.    Called By:     ReportTimer, OnVScroll, OnHScroll.
  975. */
  976.    {  // UpdateReportValues
  977.    HDC            hDC ;
  978.  
  979.    hDC = GetDC (pReport->hWnd) ;
  980.  
  981.    SetBkColor (hDC, GetSysColor(COLOR_WINDOW)) ;
  982.    SetWindowOrgEx (hDC, 
  983.                    GetScrollPos (pReport->hWnd, SB_HORZ), 
  984.                    GetScrollPos (pReport->hWnd, SB_VERT),
  985.                    NULL) ;
  986.  
  987.    DrawReportValues (hDC, pReport) ;
  988.    ReleaseDC (pReport->hWnd, hDC) ;
  989.  
  990.    }  // UpdateReportValues
  991.  
  992.  
  993.  
  994. void static OnHScroll (HWND hWnd,
  995.                        int iScrollCode,
  996.                        int iScrollNewPos)
  997.    {  // OnHScroll
  998.    PREPORT        pReport ;
  999.    int            iScrollAmt, iScrollPos, iScrollRange ;
  1000.    int            iScrollLo ;
  1001.    RECT           rectClient ;
  1002.  
  1003.    pReport = ReportData (hWnd) ;
  1004.  
  1005.    iScrollPos = GetScrollPos (hWnd, SB_HORZ) ;
  1006.    GetScrollRange (hWnd, SB_HORZ, &iScrollLo, &iScrollRange) ;
  1007.  
  1008.    GetClientRect (hWnd, &rectClient) ;
  1009.  
  1010.    switch (iScrollCode)
  1011.       {
  1012.       case SB_LINEUP:
  1013.            iScrollAmt = - Report.yLineHeight ;
  1014.            break ;
  1015.  
  1016.       case SB_LINEDOWN:
  1017.            iScrollAmt = Report.yLineHeight ;
  1018.            break ;
  1019.  
  1020.       case SB_PAGEUP:
  1021.            iScrollAmt = - (rectClient.right - rectClient.left) / 2 ;
  1022.            break ;
  1023.  
  1024.       case SB_PAGEDOWN:
  1025.            iScrollAmt = (rectClient.right - rectClient.left) / 2 ;
  1026.            break ;
  1027.  
  1028.       case SB_THUMBPOSITION:
  1029.            iScrollAmt = iScrollNewPos - iScrollPos ;
  1030.            break ;
  1031.  
  1032.       default:
  1033.            iScrollAmt = 0 ;
  1034.       }  // switch
  1035.  
  1036.      iScrollAmt = PinInclusive (iScrollAmt,
  1037.                                 -iScrollPos,
  1038.                                 iScrollRange - iScrollPos) ;
  1039.      if (iScrollAmt)
  1040.         {
  1041.         iScrollPos += iScrollAmt ;
  1042.         ScrollWindow (hWnd, -iScrollAmt, 0, NULL, NULL) ;
  1043.         SetScrollPos (hWnd, SB_HORZ, iScrollPos, TRUE) ;
  1044.         UpdateWindow (hWnd) ;
  1045.  
  1046.         UpdateReportValues (pReport) ;        
  1047.         }
  1048.    }  // OnHScroll
  1049.  
  1050.  
  1051.  
  1052. void static OnVScroll (HWND hWnd,
  1053.                        int iScrollCode,
  1054.                        int iScrollNewPos)
  1055.    {  // OnVScroll
  1056.    PREPORT        pReport ;
  1057.    int            iScrollAmt, iScrollPos, iScrollRange ;
  1058.    int            iScrollLo ;
  1059.    RECT           rectClient ;
  1060.  
  1061.    pReport = ReportData (hWnd) ;
  1062.  
  1063.    iScrollPos = GetScrollPos (hWnd, SB_VERT) ;
  1064.    GetScrollRange (hWnd, SB_VERT, &iScrollLo, &iScrollRange) ;
  1065.  
  1066.    GetClientRect (hWnd, &rectClient) ;
  1067.  
  1068.    switch (iScrollCode)
  1069.       {
  1070.       case SB_LINEUP:
  1071.            iScrollAmt = - Report.yLineHeight ;
  1072.            break ;
  1073.  
  1074.       case SB_LINEDOWN:
  1075.            iScrollAmt = Report.yLineHeight ;
  1076.            break ;
  1077.  
  1078.       case SB_PAGEUP:
  1079.            iScrollAmt = - (rectClient.bottom - rectClient.top) / 2 ;
  1080.            break ;
  1081.  
  1082.       case SB_PAGEDOWN:
  1083.            iScrollAmt = (rectClient.bottom - rectClient.top) / 2 ;
  1084.            break ;
  1085.  
  1086.       case SB_THUMBPOSITION:
  1087.            iScrollAmt = iScrollNewPos - iScrollPos ;
  1088.            break ;
  1089.  
  1090.       default:
  1091.            iScrollAmt = 0 ;
  1092.       }  // switch
  1093.  
  1094.      iScrollAmt = PinInclusive (iScrollAmt,
  1095.                                 -iScrollPos,
  1096.                                 iScrollRange - iScrollPos) ;
  1097.      if (iScrollAmt)
  1098.         {
  1099.         iScrollPos += iScrollAmt ;
  1100.         ScrollWindow (hWnd, 0, -iScrollAmt, NULL, NULL) ;
  1101.         SetScrollPos (hWnd, SB_VERT, iScrollPos, TRUE) ;
  1102.         WindowInvalidate (hWnd) ;
  1103.         UpdateWindow (hWnd) ;
  1104.  
  1105.         UpdateReportValues (pReport) ;        
  1106.         }
  1107.    }  // OnVScroll
  1108.  
  1109.  
  1110. BOOL static OnLButtonDown (HWND hWnd, 
  1111.                            WORD xPos,
  1112.                            WORD yPos)
  1113.    {
  1114.    HDC         hDC ;
  1115.    PREPORT     pReport ;
  1116.    PLINE       pLine ;
  1117.    PLINE       pLinePrevious ;
  1118.    RECT        rect ;
  1119.    POINT       pt ;
  1120.    int         xOffset, yOffset ;
  1121.  
  1122.  
  1123.    pReport = ReportData (hWnd) ;
  1124.    if (!pReport)
  1125.       return (FALSE) ;
  1126.  
  1127.    xOffset = GetScrollPos (hWnd, SB_HORZ) ;
  1128.    yOffset = GetScrollPos (hWnd, SB_VERT) ;
  1129.    pt.x = xPos + xOffset ;
  1130.    pt.y = yPos + yOffset ;
  1131.  
  1132.    pLinePrevious = pReport->pLineCurrent ;
  1133.  
  1134.    for (pLine = pReport->pLineFirst ;
  1135.         pLine ;
  1136.         pLine = pLine->pLineNext)
  1137.       {  // for
  1138.       ReportValueRect (pReport, pLine, &rect) ;
  1139.       if (PtInRect (&rect, pt))
  1140.          {
  1141.          if (pLine != pLinePrevious)
  1142.             {
  1143.             pReport->pLineCurrent = pLine ;
  1144.             hDC = GetDC (hWnd) ;
  1145.             SetWindowOrgEx (hDC, xOffset, yOffset, NULL) ;
  1146.             SelectFont (hDC, pReport->hFont) ;
  1147.             SetTextAlign (hDC, TA_RIGHT) ;
  1148.             SetBkColor (hDC, GetSysColor(COLOR_WINDOW)) ;
  1149.             DrawReportValue (hDC, pReport, pLine) ;
  1150.             if (pLinePrevious)
  1151.                DrawReportValue (hDC, pReport, pLinePrevious) ;
  1152.             
  1153.             ReleaseDC (hWnd, hDC) ;
  1154.             return (TRUE) ;
  1155.             }
  1156.          return (FALSE) ;
  1157.          }
  1158.       }  // for
  1159.  
  1160.    return (FALSE) ;
  1161.    }  // OnLButtonDown
  1162.          
  1163.          
  1164. LRESULT APIENTRY ReportWndProc (HWND hWnd,
  1165.                                WORD wMsg,
  1166.                                DWORD wParam,
  1167.                                LONG lParam)
  1168.    {  // ReportWndProc
  1169.    BOOL           bCallDefProc ;
  1170.    LRESULT        lReturnValue ;
  1171.  
  1172.    bCallDefProc = FALSE ;
  1173.    lReturnValue = 0L ;
  1174.  
  1175.    switch (wMsg)
  1176.       {  // switch
  1177.       case WM_CREATE:
  1178.          OnCreate (hWnd) ;
  1179.          break ;
  1180.  
  1181.       case WM_LBUTTONDOWN:
  1182.  
  1183.          if (!OnLButtonDown (hWnd, LOWORD (lParam), HIWORD (lParam)))
  1184.             {
  1185.             // mouse click do not hit on any entries, see if we 
  1186.             // need to drag Perfmon
  1187.             if (!(Options.bMenubar))
  1188.                {
  1189.                DoWindowDrag (lParam) ;
  1190.                }
  1191.             }
  1192.          break ;
  1193.  
  1194.       case WM_LBUTTONDBLCLK:
  1195.          SendMessage (hWndMain, WM_LBUTTONDBLCLK, wParam, lParam) ;
  1196.          break ;
  1197.  
  1198.       case WM_PAINT:
  1199.          OnPaint (hWnd) ;
  1200.          break ;
  1201.  
  1202.       case WM_SIZE:
  1203.          SetScrollRanges (hWnd) ;
  1204.          break ;
  1205.  
  1206.       case WM_HSCROLL:
  1207.          OnHScroll (hWnd, LOWORD (wParam), HIWORD (wParam)) ;
  1208.          break ;
  1209.  
  1210.       case WM_VSCROLL:
  1211.          OnVScroll (hWnd, LOWORD (wParam), HIWORD (wParam)) ;
  1212.          break ;
  1213.  
  1214.       case WM_TIMER:
  1215.          ReportTimer (hWnd, FALSE) ;
  1216.          break ;
  1217.  
  1218.       case WM_DESTROY:
  1219.          KillTimer (hWnd, ReportTimerID) ;
  1220.          break ;
  1221.  
  1222.       default:
  1223.          bCallDefProc = TRUE ;
  1224.       }  // switch
  1225.  
  1226.  
  1227.    if (bCallDefProc)
  1228.       lReturnValue = DefWindowProc (hWnd, wMsg, wParam, lParam) ;
  1229.  
  1230.    return (lReturnValue);
  1231.    }  // ReportWndProc
  1232.  
  1233.  
  1234.  
  1235. //==========================================================================//
  1236. //                             Exported Functions                           //
  1237. //==========================================================================//
  1238.  
  1239. #if 0
  1240. PREPORT ReportData (HWND hWndReport)
  1241.    {
  1242.    return (&Report) ;
  1243.    }
  1244. #endif
  1245.  
  1246. void SetReportTimer (PREPORT pReport)
  1247.    {  
  1248.    if (pReport->iStatus == iPMStatusCollecting)
  1249.       KillTimer (pReport->hWnd, ReportTimerID) ;
  1250.  
  1251.    SetTimer (pReport->hWnd, ReportTimerID, 
  1252.              pReport->iIntervalMSecs , NULL) ;
  1253.    pReport->iStatus = iPMStatusCollecting ;
  1254.    }
  1255.  
  1256.  
  1257. void ClearReportTimer (PREPORT pReport)
  1258.    {
  1259.    pReport->iStatus = iPMStatusClosed ;
  1260.    KillTimer (pReport->hWnd, ReportTimerID) ;
  1261.    }
  1262.  
  1263.  
  1264. BOOL ReportInitializeApplication (void)
  1265.    {  // ReportInitializeApplication
  1266.    BOOL           bSuccess ;
  1267.    WNDCLASS       wc ;
  1268.  
  1269.    //=============================//
  1270.    // Register ReportWindow class  //
  1271.    //=============================//
  1272.  
  1273.  
  1274.    wc.style         = dwReportClassStyle ;
  1275.    wc.lpfnWndProc   = (WNDPROC) ReportWndProc ;
  1276.    wc.hInstance     = hInstance ;
  1277.    wc.cbClsExtra    = iReportWindowExtra ;
  1278.    wc.cbWndExtra    = iReportClassExtra ;
  1279.    wc.hIcon         = NULL ;
  1280.    wc.hCursor       = LoadCursor(NULL, IDC_ARROW) ;
  1281. //   wc.hbrBackground = GetStockObject (WHITE_BRUSH) ;
  1282.    wc.hbrBackground =   (HBRUSH) (COLOR_WINDOW + 1) ;
  1283.    wc.lpszMenuName  = NULL ;
  1284.    wc.lpszClassName = szReportWindowClass ;
  1285.  
  1286.    bSuccess = RegisterClass (&wc) ;
  1287.  
  1288.  
  1289.    //=============================//
  1290.    // Register Child classes      //
  1291.    //=============================//
  1292.  
  1293.    return (bSuccess) ;
  1294.    }  // ReportInitializeApplication
  1295.  
  1296.  
  1297.  
  1298.  
  1299. BOOL ReportDeleteLine (HWND hWnd, PLINE pLine)
  1300. /*
  1301.    Effect:        Delete the line pLine into the data structures for the
  1302.                   Report of window hWnd. The line is added to the list of
  1303.                   lines, and also added to the report structure in the 
  1304.                   appropriate System, Object, and Counter.
  1305.  
  1306.    Returns:       Whether the function was successful. If this function 
  1307.                   returns FALSE, the line was not added.
  1308. */
  1309.    {  // ReportDeleteLine
  1310.    HDC            hDC ;
  1311.    PREPORT        pReport ;
  1312.    PSYSTEMGROUP   pSystemGroup ;
  1313.    POBJECTGROUP   pObjectGroup ;
  1314.    PCOUNTERGROUP  pCounterGroup ;
  1315.    BOOL           bCreatNewCounterGroup ;
  1316.  
  1317.  
  1318.    pReport = ReportData (hWnd) ;
  1319.    pReport->bModified = TRUE ;
  1320.  
  1321.    //=============================//
  1322.    // Remove line, line's system  //
  1323.    //=============================//
  1324.  
  1325.    LineRemove (&pReport->pLineFirst, pLine) ;
  1326.  
  1327.    // no more line, no more timer...
  1328.    if (!pReport->pLineFirst)
  1329.       {
  1330.       pReport->xWidth = 0 ;
  1331.       pReport->yHeight = 0 ;
  1332.       pReport->xMaxCounterWidth = 0 ;
  1333.       ClearReportTimer (pReport) ;
  1334.       }
  1335.  
  1336.  
  1337.    //=============================//
  1338.    // Get correct spot; remove line //
  1339.    //=============================//
  1340.  
  1341.    pSystemGroup = SystemGroup (pReport, pLine->lnSystemName) ;
  1342.    pObjectGroup = ObjectGroup (pSystemGroup, pLine->lnObjectName) ;
  1343.    pCounterGroup = CounterGroup (pObjectGroup, 
  1344.                               pLine->lnCounterDef.CounterNameTitleIndex,
  1345.                               &bCreatNewCounterGroup) ;
  1346.  
  1347.    if (!pCounterGroup)
  1348.       return (FALSE) ;
  1349.  
  1350.    LineCounterRemove (&pCounterGroup->pLineFirst, pLine) ;
  1351.  
  1352.    if (!(pCounterGroup->pLineFirst))
  1353.       CounterGroupRemove (&pObjectGroup->pCounterGroupFirst, pCounterGroup) ;
  1354.  
  1355.    if (!(pObjectGroup->pCounterGroupFirst))
  1356.       ObjectGroupRemove (&pSystemGroup->pObjectGroupFirst, pObjectGroup) ;
  1357.  
  1358.    if (!(pSystemGroup->pObjectGroupFirst))
  1359.       SystemGroupRemove (&pReport->pSystemGroupFirst, pSystemGroup) ;
  1360.  
  1361.  
  1362.    LineFree (pLine) ;
  1363.    pReport->pLineCurrent = pReport->pLineFirst ;
  1364.  
  1365.    if (pReport->pLineFirst)
  1366.       {
  1367.       BuildNewValueListForReport () ;
  1368.       }
  1369.  
  1370.    //=============================//
  1371.    // Calculate report positions  //
  1372.    //=============================//
  1373.  
  1374.    hDC = GetDC (hWnd) ;
  1375.    SetReportPositions (hDC, pReport) ;
  1376.    ReleaseDC (hWnd, hDC) ;
  1377.  
  1378.    WindowInvalidate (hWnd) ;
  1379.    }  // ReportDeleteLine
  1380.  
  1381.  
  1382. HWND CreateReportWindow (HWND hWndParent)
  1383. /*
  1384.    Effect:        Create the graph window. This window is a child of 
  1385.                   hWndMain and is a container for the graph data,
  1386.                   graph label, graph legend, and graph status windows.
  1387.  
  1388.    Note:          We dont worry about the size here, as this window
  1389.                   will be resized whenever the main window is resized.
  1390.  
  1391. */
  1392.    {
  1393.    return (CreateWindow (szReportWindowClass,       // window class
  1394.                          NULL,                     // caption
  1395.                          dwReportWindowStyle,       // style for window
  1396.                          0, 0,                     // initial position
  1397.                          0, 0,                     // initial size
  1398.                          hWndParent,               // parent
  1399.                          NULL,                     // menu
  1400.                          hInstance,               // program instance
  1401.                          NULL)) ;                  // user-supplied data                                              
  1402.    }  // CreateReportWindow
  1403.  
  1404.  
  1405.  
  1406.  
  1407. BOOL ReportInsertLine (HWND hWnd, PLINE pLine)
  1408. /*
  1409.    Effect:        Insert the line pLine into the data structures for the
  1410.                   Report of window hWnd. The line is added to the list of
  1411.                   lines, and also added to the report structure in the 
  1412.                   appropriate System, Object, and Counter.
  1413.  
  1414.    Returns:       Whether the function was successful. If this function 
  1415.                   returns FALSE, the line was not added.
  1416. */
  1417.    {  // ReportInsertLine
  1418.    HDC            hDC ;
  1419.    PREPORT        pReport ;
  1420.    PSYSTEMGROUP   pSystemGroup ;
  1421.    POBJECTGROUP   pObjectGroup ;
  1422.    PCOUNTERGROUP  pCounterGroup ;
  1423.    PLINE          pLineEquivalent ;
  1424.    int            OldCounterWidth ;
  1425.    BOOL           bNewCounterGroup ;
  1426.  
  1427.    pReport = ReportData (hWnd) ;
  1428.    pReport->bModified = TRUE ;
  1429.  
  1430.    pLineEquivalent = FindEquivalentLine (pLine, pReport->pLineFirst) ;
  1431.    if (pLineEquivalent) 
  1432.       {
  1433.       return (FALSE) ; 
  1434.       }
  1435.    else
  1436.       {
  1437.       //=============================//
  1438.       // Add line, line's system     //
  1439.       //=============================//
  1440.  
  1441.       LineAppend (&pReport->pLineFirst, pLine) ;
  1442.       SystemAdd (&pReport->pSystemFirst, pLine->lnSystemName) ;
  1443.  
  1444.  
  1445.       //=============================//
  1446.       // Find correct spot; add line //
  1447.       //=============================//
  1448.  
  1449.       pSystemGroup = SystemGroup (pReport, pLine->lnSystemName) ;
  1450.       pObjectGroup = ObjectGroup (pSystemGroup, pLine->lnObjectName) ;
  1451.       pCounterGroup = CounterGroup (pObjectGroup, 
  1452.                                  pLine->lnCounterDef.CounterNameTitleIndex,
  1453.                                  &bNewCounterGroup) ;
  1454.  
  1455.       if (!pCounterGroup)
  1456.          return (FALSE) ;
  1457.  
  1458.       LineCounterAppend (&pCounterGroup->pLineFirst, pLine) ;
  1459.    
  1460.       //=============================//
  1461.       // Calculate report positions  //
  1462.       //=============================//
  1463.       hDC = GetDC (hWnd) ;
  1464.       SelectFont (hDC, pReport->hFontHeaders) ;
  1465.  
  1466.       if (bNewCounterGroup)
  1467.          {
  1468.          // re-calc. the max. counter group width 
  1469.          OldCounterWidth = pReport->xMaxCounterWidth ;
  1470.          pReport->xMaxCounterWidth = 
  1471.             max (pReport->xMaxCounterWidth,
  1472.                  TextWidth (hDC, pLine->lnCounterName)) ;
  1473.          if (OldCounterWidth < pReport->xMaxCounterWidth)
  1474.             {
  1475.             // adjust the report width with the new counter width
  1476.             pReport->xWidth +=
  1477.                (pReport->xMaxCounterWidth - OldCounterWidth);
  1478.             }
  1479.          }
  1480.  
  1481.       if (!bDelayAddAction)
  1482.          {
  1483.          SetReportPositions (hDC, pReport) ;
  1484.          }
  1485.       ReleaseDC (hWnd, hDC) ;
  1486.  
  1487.       pReport->pLineCurrent = pLine ;
  1488.       
  1489.       if (!bDelayAddAction)
  1490.          {
  1491.          if (PlayingBackLog ())
  1492.             {
  1493.             PlaybackReport (hWndReport) ;
  1494.             }
  1495.          else if (pReport->iStatus == iPMStatusClosed)
  1496.             {
  1497.             SetReportTimer (pReport) ;
  1498.             }
  1499.          
  1500.          WindowInvalidate (hWnd) ;
  1501.          }
  1502.       }  // else
  1503.  
  1504.       return (TRUE) ;
  1505.    }  // ReportInsertLine
  1506.  
  1507.  
  1508.  
  1509. void SetReportPositions (HDC hDC,
  1510.                          PREPORT pReport)
  1511.    {
  1512.    PSYSTEMGROUP   pSystemGroup ;
  1513.    int            yLine ;
  1514.    int            yPos ;
  1515.  
  1516.   
  1517. //   pReport->xMaxCounterWidth = 0 ;
  1518.  
  1519.    yLine = pReport->yLineHeight ;
  1520.    yPos = 2 * yLine ;
  1521.  
  1522.    for (pSystemGroup = pReport->pSystemGroupFirst ;
  1523.         pSystemGroup ;
  1524.         pSystemGroup = pSystemGroup->pSystemGroupNext)
  1525.       {  // for
  1526.       pSystemGroup->yFirstLine = yPos + yLine ;
  1527.  
  1528.       SetSystemPositions (hDC, pReport, pSystemGroup, yLine) ;
  1529.  
  1530.       yPos = pSystemGroup->yLastLine ;
  1531.       }  // for 
  1532.  
  1533.    pReport->yHeight = yPos ;
  1534.  
  1535.    SetScrollRanges (pReport->hWnd) ;
  1536.    }  // SetReportPositions
  1537.  
  1538.  
  1539.  
  1540. void PlaybackReport (HWND hWndReport)
  1541.    {  // PlaybackReport
  1542.    PREPORT        pReport ;
  1543.  
  1544.    pReport = ReportData (hWndReport) ;
  1545.  
  1546.    PlaybackLines (pReport->pSystemFirst, 
  1547.                   pReport->pLineFirst, 
  1548.                   PlaybackLog.StartIndexPos.iPosition) ;
  1549.    PlaybackLines (pReport->pSystemFirst, 
  1550.                   pReport->pLineFirst, 
  1551.                   PlaybackLog.StopIndexPos.iPosition) ;
  1552.    }  // PlaybackReport
  1553.  
  1554.  
  1555. PLINESTRUCT CurrentReportLine (HWND hWndReport)
  1556.    {  // CurrentReportLine
  1557.    PREPORT        pReport ;
  1558.  
  1559.    pReport = ReportData (hWndReport) ;
  1560.    if (!pReport)
  1561.       return (NULL) ;
  1562.  
  1563.    return (pReport->pLineCurrent) ;
  1564.    }  // CurrentReportLine
  1565.  
  1566.  
  1567.  
  1568. BOOL AddReport (HWND hWndParent)
  1569.    {
  1570.    PREPORT        pReport ;
  1571.  
  1572.    pReport = ReportData (hWndReport) ;
  1573.  
  1574.    return (AddLine (hWndParent, 
  1575.                     &(pReport->pSystemFirst), 
  1576.                     &(pReport->Visual), 
  1577.                     LineTypeReport)) ;
  1578.    }
  1579.  
  1580.  
  1581.  
  1582. BOOL EditReport (HWND hWndParent)
  1583.    {  // EditReport
  1584.    PREPORT        pReport ;
  1585.  
  1586.    pReport = ReportData (hWndReport) ;
  1587.  
  1588.    return (EditLine (hWndParent, 
  1589.                      &(pReport->pSystemFirst), 
  1590.                      CurrentReportLine (hWndReport),
  1591.                      LineTypeReport)) ;
  1592.    }  // EditReport
  1593.  
  1594.  
  1595. BOOL ToggleReportRefresh (HWND hWnd)
  1596.    {  // ToggleReportRefresh
  1597.    PREPORT        pReport ;
  1598.  
  1599.    pReport = ReportData (hWnd) ;
  1600.  
  1601.    if (pReport->bManualRefresh)
  1602.       SetReportTimer (pReport) ;
  1603.    else
  1604.       ClearReportTimer (pReport) ;
  1605.  
  1606.    pReport->bManualRefresh = !pReport->bManualRefresh ;
  1607.    return (pReport->bManualRefresh) ;
  1608.    }  // ToggleReportRefresh
  1609.  
  1610. BOOL ReportRefresh (HWND hWnd)
  1611.    {  // ReportRefresh
  1612.    PREPORT        pReport ;
  1613.  
  1614.    pReport = ReportData (hWnd) ;
  1615.  
  1616.    return (pReport->bManualRefresh) ;
  1617.    }  // ReportRefresh
  1618.  
  1619.  
  1620.  
  1621. void ReportTimer (HWND hWnd, BOOL bForce)
  1622.    {
  1623.    PREPORT        pReport ;
  1624.  
  1625.    pReport = ReportData (hWnd) ;
  1626.  
  1627.    if (PlayingBackLog () || !pReport)
  1628.       {
  1629.       return;
  1630.       }
  1631.  
  1632.    if (bForce || !pReport->bManualRefresh)
  1633.       {  // if
  1634.       UpdateLines (&(pReport->pSystemFirst), pReport->pLineFirst) ;
  1635.       if (iPerfmonView == IDM_VIEWREPORT && !bPerfmonIconic)
  1636.          {
  1637.          // only need to draw the data when we are viewing it...
  1638.          UpdateReportValues (pReport) ;
  1639.          }
  1640.       }  // if
  1641.    }  // ReportTimer
  1642.  
  1643.  
  1644.  
  1645.  
  1646.  
  1647.  
  1648. BOOL SaveReport (HWND hWndReport, HANDLE hInputFile, BOOL bGetFileName)
  1649.    {
  1650.    PREPORT        pReport ;
  1651.    PLINE          pLine ;
  1652.    HANDLE         hFile ;
  1653.    DISKREPORT     DiskReport ;
  1654.    PERFFILEHEADER FileHeader ;
  1655.    TCHAR          szFileName [256] ;
  1656.    BOOL           newFileName = FALSE ;
  1657.  
  1658.    pReport = ReportData (hWndReport) ;
  1659.    if (!pReport)
  1660.       {
  1661.       return (FALSE) ;
  1662.       }
  1663.  
  1664.    if (hInputFile)
  1665.       {
  1666.       // use the input file handle if it is available
  1667.       // this is the case for saving workspace data
  1668.       hFile = hInputFile ;
  1669.       }
  1670.    else
  1671.       {
  1672.       if (pReportFullFileName)
  1673.          {
  1674.          lstrcpy (szFileName, pReportFullFileName) ;
  1675.          }
  1676.       if (bGetFileName || pReportFullFileName == NULL)
  1677.          {
  1678. //         if (pReportFullFileName == NULL)
  1679. //            {
  1680. //            StringLoad (IDS_REPORT_FNAME, szFileName) ;
  1681. //            }
  1682.          if (!FileGetName (hWndReport, IDS_REPORTFILE, szFileName))
  1683.             {
  1684.             return (FALSE) ;
  1685.             }
  1686.          newFileName = TRUE ;
  1687.          }
  1688.  
  1689.       hFile = FileHandleCreate (szFileName) ;
  1690.  
  1691.       if (hFile && newFileName)
  1692.          {
  1693.          ChangeSaveFileName (szFileName, IDM_VIEWREPORT) ;
  1694.          }
  1695.       else if (!hFile)
  1696.          {
  1697.          DlgErrorBox (hWndReport, ERR_CANT_OPEN, szFileName) ;
  1698.          }
  1699.       }
  1700.  
  1701.  
  1702.    if (!hFile)
  1703.       return (FALSE) ;
  1704.  
  1705.  
  1706.    if (!hInputFile)
  1707.       {
  1708.       memset (&FileHeader, 0, sizeof (FileHeader)) ;
  1709.       lstrcpy (FileHeader.szSignature, szPerfReportSignature) ;
  1710.       FileHeader.dwMajorVersion = ReportMajorVersion ;
  1711.       FileHeader.dwMinorVersion = ReportMinorVersion ;
  1712.    
  1713.       if (!FileWrite (hFile, &FileHeader, sizeof (PERFFILEHEADER)))
  1714.          {
  1715.          goto Exit0 ;
  1716.          }
  1717.       }
  1718.  
  1719.    DiskReport.Visual = pReport->Visual ;
  1720.    DiskReport.bManualRefresh = pReport->bManualRefresh ;
  1721.    DiskReport.dwIntervalSecs = pReport->iIntervalMSecs ;
  1722.    DiskReport.dwNumLines = NumLines (pReport->pLineFirst) ;
  1723.    DiskReport.perfmonOptions = Options ;
  1724.  
  1725.    if (!FileWrite (hFile, &DiskReport, sizeof (DISKREPORT)))
  1726.       {
  1727.       goto Exit0 ;
  1728.       }
  1729.  
  1730.    for (pLine = pReport->pLineFirst ;
  1731.         pLine ;
  1732.         pLine = pLine->pLineNext)
  1733.       {  // for
  1734.       if (!WriteLine (pLine, hFile))
  1735.          {
  1736.          goto Exit0 ;
  1737.          }
  1738.       }  // for
  1739.  
  1740.    if (!hInputFile)
  1741.       {
  1742.       CloseHandle (hFile) ;
  1743.       }
  1744.  
  1745.    return (TRUE) ;
  1746.  
  1747. Exit0:
  1748.    if (!hInputFile)
  1749.       {
  1750.       CloseHandle (hFile) ;
  1751.  
  1752.       // only need to report error if not workspace 
  1753.       DlgErrorBox (hWndReport, ERR_SETTING_FILE, szFileName) ;
  1754.       }
  1755.    return (FALSE) ;
  1756.    }  // SaveReport  
  1757.  
  1758.  
  1759. void ReportAddAction (PREPORT pReport)
  1760.    {
  1761.    HDC      hDC ;
  1762.  
  1763.    //=============================//
  1764.    // Calculate report positions  //
  1765.    //=============================//
  1766.  
  1767.    hDC = GetDC (hWndReport) ;
  1768.    SetReportPositions (hDC, pReport) ;
  1769.    ReleaseDC (hWndReport, hDC) ;
  1770.    
  1771.    if (PlayingBackLog ())
  1772.       {
  1773.       PlaybackReport (hWndReport) ;
  1774.       }
  1775.    else if (pReport->iStatus == iPMStatusClosed)
  1776.       {
  1777.       SetReportTimer (pReport) ;
  1778.       }
  1779.  
  1780.    WindowInvalidate (hWndReport) ;
  1781.    }
  1782.  
  1783.  
  1784. BOOL OpenReportVer1 (HANDLE hFile,
  1785.                      DISKREPORT *pDiskReport,
  1786.                      PREPORT pReport,
  1787.                      DWORD dwMinorVersion)
  1788.    {
  1789.    HDC   hDC ;
  1790.  
  1791.    pReport->Visual = pDiskReport->Visual ;
  1792.    pReport->iIntervalMSecs = pDiskReport->dwIntervalSecs ;
  1793.    if (dwMinorVersion < 3)
  1794.       {
  1795.       // convert this to msec
  1796.       pReport->iIntervalMSecs *= 1000 ;
  1797.       }
  1798.    pReport->bManualRefresh = pDiskReport->bManualRefresh ;
  1799.  
  1800.    bDelayAddAction = TRUE ;
  1801.    ReadLines (hFile, pDiskReport->dwNumLines,
  1802.              &(pReport->pSystemFirst), &(pReport->pLineFirst), IDM_VIEWREPORT) ;
  1803.    bDelayAddAction = FALSE ;
  1804.  
  1805.    //=============================//
  1806.    // Calculate report positions  //
  1807.    //=============================//
  1808.  
  1809.    hDC = GetDC (hWndReport) ;
  1810.    SetReportPositions (hDC, pReport) ;
  1811.    ReleaseDC (hWndReport, hDC) ;
  1812.  
  1813.    if (PlayingBackLog ())
  1814.  
  1815.       {
  1816.       PlaybackReport (hWndReport) ;
  1817.       }
  1818.    else if (pReport->iStatus == iPMStatusClosed)
  1819.       {
  1820.       SetReportTimer (pReport) ;
  1821.       }
  1822.  
  1823.    WindowInvalidate (hWndReport) ;
  1824.  
  1825.    return (TRUE) ;
  1826.    }  // OpenReportVer1
  1827.  
  1828.  
  1829.  
  1830. BOOL OpenReport (HWND hWndReport, 
  1831.                  HANDLE hFile, 
  1832.                  DWORD dwMajorVersion,
  1833.                  DWORD dwMinorVersion,
  1834.                  BOOL bReportFile)
  1835.    {
  1836.    PREPORT        pReport ;
  1837.    DISKREPORT     DiskReport ;
  1838.    BOOL           bSuccess = TRUE ;
  1839.  
  1840.    pReport = ReportData (hWndReport) ;
  1841.    if (!pReport)
  1842.       {
  1843.       bSuccess = FALSE ;
  1844.       goto Exit0 ;
  1845.       }
  1846.  
  1847.    if (!FileRead (hFile, &DiskReport, sizeof (DISKREPORT)))
  1848.       {
  1849.       bSuccess = FALSE ;
  1850.       goto Exit0 ;
  1851.       }
  1852.  
  1853.  
  1854.    switch (dwMajorVersion)
  1855.       {
  1856.       case (1):
  1857.          
  1858.          SetHourglassCursor() ;
  1859.      
  1860.          ResetReportView (hWndReport) ;
  1861.  
  1862.          OpenReportVer1 (hFile, &DiskReport, pReport, dwMinorVersion) ;
  1863.  
  1864.          // change to report view if we are opening a 
  1865.          // report file
  1866.          if (bReportFile && iPerfmonView != IDM_VIEWREPORT)
  1867.             {
  1868.             SendMessage (hWndMain, WM_COMMAND, (LONG)IDM_VIEWREPORT, 0L) ;
  1869.             }
  1870.  
  1871.          if (iPerfmonView == IDM_VIEWREPORT)
  1872.             {
  1873.             SetPerfmonOptions (&DiskReport.perfmonOptions) ;
  1874.             }
  1875.  
  1876.          SetArrowCursor() ;
  1877.  
  1878.          break ;
  1879.       }  // switch
  1880.  
  1881. Exit0:
  1882.       
  1883.    if (bReportFile)
  1884.       {
  1885.       CloseHandle (hFile) ;
  1886.       }
  1887.  
  1888.    return (bSuccess) ;
  1889.    }  // OpenReport
  1890.    
  1891.  
  1892.  
  1893. BOOL QuerySaveReport (HWND hWndParent, 
  1894.                       HWND hWndReport)
  1895.    {  // QuerySaveReport
  1896. #ifdef KEEP_QUERY
  1897.    PREPORT        pReport ;
  1898.    int            iReturn ;
  1899.  
  1900.    pReport = ReportData (hWndReport) ;
  1901.    if (!pReport)
  1902.       return (TRUE) ;
  1903.  
  1904.    if (!pReport->bModified)
  1905.       return (TRUE) ;
  1906.  
  1907.    iReturn = MessageBoxResource (hWndParent, 
  1908.                                  IDS_SAVEREPORT, IDS_MODIFIEDREPORT,
  1909.                                  MB_YESNOCANCEL | MB_ICONASTERISK) ;
  1910.  
  1911.    if (iReturn == IDCANCEL)
  1912.       return (FALSE) ;
  1913.  
  1914.    if (iReturn == IDYES)
  1915.       SaveReport (hWndReport) ;
  1916. #endif
  1917.  
  1918.    return (TRUE) ;
  1919.    }  // QuerySaveReport
  1920.  
  1921. void ResetReportView (HWND hWndReport)
  1922.    {  // ResetReportView
  1923.    PREPORT        pReport ;
  1924.  
  1925.    pReport = ReportData (hWndReport) ;
  1926.    
  1927.    if (!pReport)
  1928.       {
  1929.       return ;
  1930.       }
  1931.    
  1932.    ChangeSaveFileName (NULL, IDM_VIEWREPORT) ;
  1933.  
  1934.    if (pReport->pSystemGroupFirst)
  1935.       {
  1936.       ResetReport (hWndReport) ;
  1937.       }
  1938.    }  // ResetReportView
  1939.  
  1940.  
  1941. void ResetReport (HWND hWndReport)
  1942.    {  // ResetReport
  1943.    PREPORT        pReport ;
  1944.    PSYSTEMGROUP   pSystemGroup, pSystemGroupDelete ;
  1945.    POBJECTGROUP   pObjectGroup, pObjectGroupDelete ;
  1946.    PCOUNTERGROUP  pCounterGroup, pCounterGroupDelete ;
  1947.    HDC            hDC ;
  1948.  
  1949.    pReport = ReportData (hWndReport) ;
  1950.    if (!pReport)
  1951.       return ;
  1952.  
  1953.    ClearReportTimer (pReport) ;
  1954.  
  1955.    pSystemGroup = pReport->pSystemGroupFirst ;
  1956.    while (pSystemGroup)
  1957.       { 
  1958.       pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  1959.       while (pObjectGroup)
  1960.          {
  1961.          pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  1962.          while (pCounterGroup)
  1963.             {
  1964.             pCounterGroupDelete = pCounterGroup ;
  1965.             pCounterGroup = pCounterGroup->pCounterGroupNext ;
  1966.             MemoryFree (pCounterGroupDelete) ;
  1967.             }  // while pCounter...
  1968.          
  1969.          pObjectGroupDelete = pObjectGroup ;
  1970.          pObjectGroup = pObjectGroup->pObjectGroupNext ;
  1971.          ColumnGroupRemove (pObjectGroupDelete->pColumnGroupFirst) ;
  1972.          MemoryFree (pObjectGroupDelete->lpszObjectName) ;
  1973.          MemoryFree (pObjectGroupDelete) ;
  1974.          }  // while pObject
  1975.  
  1976.       pSystemGroupDelete = pSystemGroup ;
  1977.       pSystemGroup = pSystemGroup->pSystemGroupNext ;
  1978.       MemoryFree (pSystemGroupDelete->lpszSystemName) ;
  1979.       MemoryFree (pSystemGroupDelete) ;
  1980.       }  // while pSystem...
  1981.  
  1982.    FreeLines (pReport->pLineFirst) ;
  1983.    pReport->pLineFirst = NULL ;
  1984.  
  1985.    FreeSystems (pReport->pSystemFirst) ;
  1986.    pReport->pSystemFirst = NULL ;
  1987.  
  1988.    pReport->pSystemGroupFirst = NULL ;
  1989.    pReport->pLineCurrent = NULL ;
  1990.  
  1991.    // reset scrolling ranges
  1992.    pReport->xWidth = 0 ;
  1993.    pReport->yHeight = 0 ;
  1994.    pReport->xMaxCounterWidth = 0 ;
  1995.    hDC = GetDC (hWndReport) ;
  1996.    SetReportPositions (hDC, pReport) ;
  1997.    ReleaseDC (hWndReport, hDC) ;
  1998.  
  1999.    WindowInvalidate (hWndReport) ;
  2000.    }  // ResetReport
  2001.    
  2002. void ClearReportDisplay (HWND hWndReport)
  2003.    {  // ResetReport
  2004.    PREPORT        pReport ;
  2005.    PLINE          pLine;
  2006.  
  2007.    if (PlayingBackLog())
  2008.       {
  2009.       return ;
  2010.       }
  2011.  
  2012.    pReport = ReportData (hWndReport) ;
  2013.    if (!pReport || !pReport->pLineFirst)
  2014.       return ;
  2015.  
  2016.    for (pLine = pReport->pLineFirst ;
  2017.         pLine ;
  2018.         pLine = pLine->pLineNext)
  2019.       {
  2020.       // reset the new data counts
  2021.       pLine->bFirstTime = 2 ;
  2022.       }
  2023.  
  2024.    // re-draw the values
  2025.    UpdateReportValues (pReport) ;
  2026.  
  2027.    }  // ClearReportDisplay
  2028.  
  2029. //=========================================
  2030. // we don't print. we just export
  2031. //
  2032. // if need printint, define KEEP_PRINT
  2033. //=========================================
  2034. #ifdef KEEP_PRINT
  2035. BOOL PrintReportDisplay (HDC hDC,
  2036.                          PREPORT pReport)
  2037.    {
  2038.    SetReportPositions (hDC, pReport) ;
  2039.    DrawReport (hDC, pReport) ;
  2040.    return TRUE ;
  2041.    }  // PrintReportDisplay
  2042.  
  2043.  
  2044.  
  2045. BOOL PrintReport (HWND hWndParent,
  2046.                   HWND hWndReport)
  2047.    {
  2048.    PREPORT        pReport ;
  2049.    HDC            hDC ;
  2050.    int            xPageWidth ;
  2051.    int            yPageHeight ;
  2052.    int            xValueWidth ;
  2053.  
  2054.    HFONT          hFont, hFontHeaders ;
  2055.    int            yLineHeight ;
  2056.  
  2057.    pReport = ReportData (hWndReport) ;
  2058.    if (!pReport)
  2059.       return (FALSE) ;
  2060.  
  2061.    hDC = PrintDC () ;
  2062.    if (!hDC)
  2063.       {
  2064.       PostError () ;
  2065.       return (FALSE) ;
  2066.       }
  2067.       
  2068.    xPageWidth = GetDeviceCaps (hDC, HORZRES) ;
  2069.    yPageHeight = GetDeviceCaps (hDC, VERTRES) ;
  2070.  
  2071.    
  2072.    StartJob (hDC, TEXT("Performance Monitor Report")) ;
  2073.    StartPage (hDC) ;   
  2074.  
  2075.  
  2076.    hFont = pReport->hFont ;
  2077.    hFontHeaders = pReport->hFontHeaders ;
  2078.    yLineHeight = pReport->yLineHeight ;
  2079.    xValueWidth = pReport->xValueWidth ;
  2080.  
  2081.    pReport->hFont = hFontPrinterScales ;
  2082.    pReport->hFontHeaders = hFontPrinterScalesBold ;
  2083.  
  2084.    SelectFont (hDC, pReport->hFont) ;
  2085.    pReport->yLineHeight = FontHeight (hDC, TRUE) ;
  2086.  
  2087.    pReport->xValueWidth = TextWidth (hDC, szValuePlaceholder) ;
  2088.  
  2089.    PrintReportDisplay (hDC, pReport) ;
  2090.  
  2091.    EndPage (hDC) ;
  2092.    EndJob (hDC) ;
  2093.    
  2094.    DeleteDC (hDC) ;
  2095.  
  2096.  
  2097.    pReport->hFont = hFont ;
  2098.    pReport->hFontHeaders = hFontHeaders ;
  2099.    pReport->yLineHeight = yLineHeight ;
  2100.  
  2101.    pReport->xValueWidth = xValueWidth ;
  2102.  
  2103.    hDC = GetDC ()hWndReport) ;
  2104.    SetReportPositions (hDC, pReport) ;
  2105.    ReleaseDC (hWndReport, hDC) ;
  2106.  
  2107.    return (FALSE) ;
  2108.    }  // PrintReport
  2109.  
  2110. // we don't print. we just export
  2111. #endif
  2112.  
  2113. BOOL ExportComputerName (HANDLE hFile, PSYSTEMGROUP pSystemGroup)
  2114. {
  2115.    int            StringLen ;
  2116.    BOOL           bWriteSuccess = TRUE ;
  2117.    CHAR           TempBuff [LongTextLen] ;
  2118.    TCHAR          UnicodeBuff [LongTextLen] ;
  2119.  
  2120.    // export computer name
  2121.    strcpy (TempBuff, LineEndStr) ;
  2122.    strcat (TempBuff, LineEndStr) ;
  2123.    StringLen = strlen (TempBuff) ;
  2124.    TSPRINTF (UnicodeBuff, szSystemFormat, pSystemGroup->lpszSystemName) ;
  2125.    ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  2126.    strcat (TempBuff, LineEndStr) ;
  2127.  
  2128.    if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
  2129.       {
  2130.       bWriteSuccess = FALSE ; 
  2131.       }
  2132.  
  2133.    return (bWriteSuccess) ;
  2134. }  // ExportComputerName
  2135.  
  2136. BOOL ExportObjectName (HANDLE hFile, POBJECTGROUP pObjectGroup, int *pColNum)
  2137. {
  2138.    int            StringLen ;
  2139.    BOOL           bNeedToExport ;
  2140.    BOOL           bWriteSuccess = TRUE ;
  2141.    CHAR           TempBuff [LongTextLen] ;
  2142.    TCHAR          UnicodeBuff [LongTextLen] ;
  2143.    PCOLUMNGROUP   pColumnGroup ;
  2144.    int            ParentNum, InstanceNum ;
  2145.  
  2146.  
  2147.    ParentNum = InstanceNum = 0 ;
  2148.  
  2149.    if (pColNum)
  2150.       {
  2151.       *pColNum = 0 ;
  2152.       }
  2153.  
  2154.    // export object name
  2155.    strcpy (TempBuff, LineEndStr) ;
  2156.    StringLen = strlen (TempBuff) ;
  2157.    TSPRINTF (UnicodeBuff, szObjectFormat, pObjectGroup->lpszObjectName) ;
  2158.    ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  2159.    strcat (TempBuff, LineEndStr) ;
  2160.  
  2161.    if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
  2162.       {
  2163.       goto Exit0 ;
  2164.       }
  2165.    
  2166.  
  2167.    // export column group
  2168.    if (pObjectGroup->pColumnGroupFirst)
  2169.       {
  2170.       strcpy (TempBuff, pDelimiter) ;
  2171.       strcat (TempBuff, pDelimiter) ;
  2172.       StringLen = strlen (TempBuff) ;
  2173.  
  2174.       bNeedToExport = FALSE ;
  2175.  
  2176.       // export Parent Names
  2177.       for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  2178.            pColumnGroup ;
  2179.            pColumnGroup = pColumnGroup->pColumnGroupNext)
  2180.          {  // for
  2181.  
  2182.          if (pColumnGroup->lpszParentName)
  2183.             {
  2184.             ParentNum++ ;
  2185.             bNeedToExport = TRUE ;
  2186.             ConvertUnicodeStr (&TempBuff[StringLen],
  2187.                                pColumnGroup->lpszParentName) ;
  2188.             StringLen = strlen (TempBuff) ;
  2189.             }
  2190.                         
  2191.          strcat (&TempBuff[StringLen], pDelimiter) ;
  2192.          StringLen = strlen (TempBuff) ;
  2193.          }
  2194.           
  2195.       if (bNeedToExport)
  2196.          {
  2197.          // only need to export when there is Parent Instance
  2198.          strcat (&TempBuff[StringLen], LineEndStr) ;
  2199.          if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
  2200.             {
  2201.             goto Exit0 ;
  2202.             }
  2203.          }
  2204.       else
  2205.          {
  2206.          ParentNum = 0 ;
  2207.          }
  2208.  
  2209.  
  2210.       // setup to export Instances
  2211.       strcpy (TempBuff, pDelimiter) ;
  2212.       strcat (TempBuff, pDelimiter) ;
  2213.       StringLen = strlen (TempBuff) ;
  2214.       bNeedToExport = FALSE ;
  2215.  
  2216.       // export Instance Names
  2217.       for (pColumnGroup = pObjectGroup->pColumnGroupFirst ;
  2218.            pColumnGroup ;
  2219.            pColumnGroup = pColumnGroup->pColumnGroupNext)
  2220.          {  // for
  2221.  
  2222.          if (pColumnGroup->lpszInstanceName)
  2223.             {
  2224.             InstanceNum++ ;
  2225.             bNeedToExport = TRUE ;
  2226.             ConvertUnicodeStr (&TempBuff[StringLen],
  2227.                                pColumnGroup->lpszInstanceName) ;
  2228.             StringLen = strlen (TempBuff) ;
  2229.             }
  2230.                
  2231.          strcat (&TempBuff[StringLen], pDelimiter) ;
  2232.          StringLen = strlen (TempBuff) ;
  2233.          }
  2234.  
  2235.       if (bNeedToExport)
  2236.          {
  2237.          strcat (&TempBuff[StringLen], LineEndStr) ;
  2238.          if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
  2239.             {
  2240.             goto Exit0 ;
  2241.             }
  2242.          }
  2243.       else
  2244.          {
  2245.          InstanceNum = 0 ;
  2246.          }
  2247.       }
  2248.  
  2249.    if (pColNum)
  2250.       {
  2251.       *pColNum = max (ParentNum, InstanceNum) ;
  2252.       }
  2253.  
  2254.    return (TRUE) ;
  2255.  
  2256. Exit0:
  2257.    return (FALSE) ;
  2258.  
  2259. }  // ExportObjectName
  2260.  
  2261. BOOL ExportLineName (HANDLE hFile, PLINE pLine, int *pExportCounterName)
  2262. {
  2263.    FLOAT          eValue ;
  2264.    int            StringLen ;
  2265.    BOOL           bWriteSuccess = TRUE ;
  2266.    CHAR           TempBuff [LongTextLen] ;
  2267.    TCHAR          UnicodeBuff [LongTextLen] ;
  2268.  
  2269.  
  2270.    strcpy (TempBuff, pDelimiter) ;
  2271.    
  2272.    if (*pExportCounterName)
  2273.       {
  2274.       StringLen = strlen (TempBuff) ;
  2275.       ConvertUnicodeStr (&TempBuff[StringLen], pLine->lnCounterName) ;
  2276.       strcat (TempBuff, pDelimiter) ;
  2277.       *pExportCounterName = FALSE ;
  2278.       }
  2279.    StringLen = strlen (TempBuff) ;
  2280.  
  2281.    if (pLine->bFirstTime == 0)
  2282.       {
  2283.       eValue = (*(pLine->valNext)) (pLine) ;
  2284.       TSPRINTF (UnicodeBuff,
  2285.                 (eValue > eStatusLargeValueMax) ?
  2286.                     szLargeValueFormat : szValueFormat,
  2287.                 eValue) ;
  2288.       ConvertUnicodeStr (&TempBuff[StringLen], UnicodeBuff) ;
  2289.       }
  2290.    else
  2291.       {
  2292.       // export "----" for unstable values
  2293.       strcat (&TempBuff[StringLen], "----");
  2294.       }
  2295.  
  2296.    // write the line value, it may be inefficient but we
  2297.    // don't want to overflow TempBuff with line values..
  2298.    if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
  2299.       {
  2300.       goto Exit0 ;
  2301.       }
  2302.  
  2303.    return (TRUE) ;
  2304.  
  2305.  
  2306. Exit0:
  2307.    return (FALSE) ;
  2308. }  // ExportLineName
  2309.  
  2310.  
  2311. // This routine is need to insert the line values into its
  2312. // column location.  It is needed because not all the instances (columns)
  2313. // are available for the same line.
  2314. void SaveColumnLineData (PLINE pLine, LPSTR pColumnLineData)
  2315. {
  2316.    FLOAT          eValue ;
  2317.    LPSTR          pColumnLine ;
  2318.    CHAR           TempBuff [LongTextLen] ;
  2319.    TCHAR          UnicodeBuff [LongTextLen] ;
  2320.  
  2321.    if (!pColumnLineData)
  2322.       {
  2323.       return ;
  2324.       }
  2325.  
  2326.    // find the offset into the pColumnLineData buffer for current line
  2327.    pColumnLine = pColumnLineData + pLine->iScaleIndex * ShortTextLen ;
  2328.  
  2329.    if (pLine->bFirstTime == 0)
  2330.       {
  2331.       eValue = (*(pLine->valNext)) (pLine) ;
  2332.       TSPRINTF (UnicodeBuff,
  2333.                 (eValue > eStatusLargeValueMax) ?
  2334.                     szLargeValueFormat : szValueFormat,
  2335.                 eValue) ;
  2336.  
  2337.       ConvertUnicodeStr (TempBuff, UnicodeBuff) ;
  2338.       strncpy (pColumnLine, TempBuff, ShortTextLen) ;
  2339.       *(pColumnLine + ShortTextLen - 1) = '\0' ;
  2340.       }
  2341.    else
  2342.       {
  2343.       // export "----" for unstable values
  2344.       strcpy (pColumnLine, "----");
  2345.       }
  2346. }  // SaveColumnLineData
  2347.  
  2348. BOOL ExportColumnLineData (HANDLE hFile,
  2349.                            int ColumnTotal,
  2350.                            PCOUNTERGROUP pCounterGroup,
  2351.                            LPSTR pColumnLineData)
  2352. {
  2353.    int            iIndex ;
  2354.    int            StringLen ;
  2355.    CHAR           TempBuff [LongTextLen] ;
  2356.    LPSTR          pCurrentLineData ;
  2357.  
  2358.    // export the counter name
  2359.    strcpy (TempBuff, pDelimiter) ;
  2360.    StringLen = strlen (TempBuff) ;
  2361.    ConvertUnicodeStr (&TempBuff[StringLen], pCounterGroup->pLineFirst->lnCounterName) ;
  2362.    strcat (TempBuff, pDelimiter) ;
  2363.    if (!FileWrite (hFile, TempBuff, strlen(TempBuff)))
  2364.       {
  2365.       goto Exit0 ;
  2366.       }
  2367.  
  2368.    // go thru each column and export the line value if it has been stored   
  2369.    for (iIndex = 0, pCurrentLineData = pColumnLineData ;
  2370.       iIndex < ColumnTotal ;
  2371.       iIndex++, pCurrentLineData += ShortTextLen )
  2372.       {
  2373.       if (*pCurrentLineData != 0)
  2374.          {
  2375.          // data available for this column
  2376.          if (!FileWrite (hFile, pCurrentLineData, strlen(pCurrentLineData)))
  2377.             {
  2378.             goto Exit0 ;
  2379.             }
  2380.          }
  2381.  
  2382.       if (!FileWrite (hFile, pDelimiter, strlen(pDelimiter)))
  2383.          {
  2384.          goto Exit0 ;
  2385.          }
  2386.       }
  2387.  
  2388.    if (!FileWrite (hFile, LineEndStr, strlen(LineEndStr)))
  2389.       {
  2390.       goto Exit0 ;
  2391.       }
  2392.  
  2393.    return (TRUE) ;
  2394.  
  2395.  
  2396. Exit0:
  2397.    return (FALSE) ;
  2398.  
  2399. }  // ExportColumnLineData
  2400.  
  2401. void ExportReport (void)
  2402. {
  2403.    HANDLE         hFile = 0 ;
  2404.    PREPORT        pReport ;
  2405.    PSYSTEMGROUP   pSystemGroup ;
  2406.    POBJECTGROUP   pObjectGroup ;
  2407.    PCOUNTERGROUP  pCounterGroup ;
  2408.    PLINE          pLine ;
  2409.    BOOL           bExportComputer ;
  2410.    BOOL           bExportObject ;
  2411.    BOOL           bExportCounterName ;
  2412.    int            ColumnTotal = 0 ;
  2413.    LPSTR          pColumnLineData = NULL ;
  2414.    LPTSTR         pFileName = NULL ;
  2415.    INT            ErrCode = 0 ;
  2416.  
  2417.    if (!(pReport = ReportData (hWndReport)))
  2418.       {
  2419.       return ;
  2420.       }
  2421.  
  2422.    // see if there is anything to export..
  2423.    if (!(pReport->pSystemGroupFirst))
  2424.       {
  2425.       return ;
  2426.       }
  2427.  
  2428.    SetHourglassCursor() ;
  2429.    
  2430.    if (ErrCode = ExportFileOpen (hWndReport, &hFile,
  2431.        pReport->iIntervalMSecs, &pFileName))
  2432.       {
  2433.       goto Exit0 ;
  2434.       }
  2435.  
  2436.    if (!pFileName)
  2437.       {
  2438.       // the case when user cancel
  2439.       goto Exit0 ;
  2440.       }
  2441.  
  2442.    // export each system group
  2443.  
  2444.    for (pSystemGroup = pReport->pSystemGroupFirst ;
  2445.         pSystemGroup ;
  2446.         pSystemGroup = pSystemGroup->pSystemGroupNext)
  2447.       {  // for System...
  2448.  
  2449.       bExportComputer = TRUE ;
  2450.  
  2451.       for (pObjectGroup = pSystemGroup->pObjectGroupFirst ;
  2452.            pObjectGroup ;
  2453.            pObjectGroup = pObjectGroup->pObjectGroupNext)
  2454.          {  // for Object...
  2455.  
  2456.          bExportObject = TRUE ;
  2457.  
  2458.          for (pCounterGroup = pObjectGroup->pCounterGroupFirst ;
  2459.               pCounterGroup ;
  2460.               pCounterGroup = pCounterGroup->pCounterGroupNext)
  2461.             {  // for Counter...
  2462.  
  2463.             bExportCounterName = TRUE ;
  2464.  
  2465.             // Column data buffer has been allocated for this object type, 
  2466.             // zero out the buffer and prepare for next round.
  2467.          
  2468.             if (pColumnLineData)
  2469.                {
  2470.                memset (pColumnLineData, 0, ColumnTotal * ShortTextLen) ;
  2471.                }
  2472.  
  2473.             for (pLine = pCounterGroup->pLineFirst ;
  2474.                  pLine ;
  2475.                  pLine = pLine->pLineCounterNext)
  2476.                {  // for Line...
  2477.  
  2478.                if (bExportComputer)
  2479.                   {
  2480.                   // only need to do this for the first object
  2481.                   bExportComputer = FALSE ;
  2482.                   if (!ExportComputerName (hFile, pSystemGroup))
  2483.                      {
  2484.                      ErrCode = ERR_EXPORT_FILE ;
  2485.                      goto Exit0 ;
  2486.                      }
  2487.                   }
  2488.  
  2489.                if (bExportObject)
  2490.                   {
  2491.                   // only need to do this for the first counter group
  2492.                   bExportObject = FALSE ;
  2493.                   if (!ExportObjectName (hFile, pObjectGroup, &ColumnTotal))
  2494.                      {
  2495.                      ErrCode = ERR_EXPORT_FILE ;
  2496.                      goto Exit0 ;
  2497.                      }
  2498.  
  2499.                   if (ColumnTotal > 1)
  2500.                      {
  2501.                      // special case to setup a column array and export
  2502.                      // the line values later
  2503.                      pColumnLineData = MemoryAllocate (ColumnTotal * ShortTextLen) ;
  2504.                      if (!pColumnLineData)
  2505.                         {
  2506.                         ErrCode = ERR_EXPORT_FILE ;
  2507.                         goto Exit0 ;
  2508.                         }
  2509.                      }
  2510.                   }
  2511.  
  2512.                if (ColumnTotal > 1)
  2513.                   {
  2514.                   // save the line value into its column & export later
  2515.                   SaveColumnLineData (pLine, pColumnLineData) ;
  2516.                   }
  2517.                else
  2518.                   {
  2519.                   // simple case, export the line now
  2520.                   if (!ExportLineName (hFile, pLine, &bExportCounterName))
  2521.                      {
  2522.                      ErrCode = ERR_EXPORT_FILE ;
  2523.                      goto Exit0 ;
  2524.                      }
  2525.                   }
  2526.                }  // for Line...
  2527.  
  2528.             if (!bExportCounterName)
  2529.                {
  2530.                // export the line end
  2531.                if (!FileWrite (hFile, LineEndStr, strlen(LineEndStr)))
  2532.                   {
  2533.                   ErrCode = ERR_EXPORT_FILE ;
  2534.                   goto Exit0 ;
  2535.                   }
  2536.                }
  2537.  
  2538.             if (pColumnLineData)
  2539.                {
  2540.                // now, do the actual export
  2541.                if (!ExportColumnLineData (hFile,
  2542.                   ColumnTotal,
  2543.                   pCounterGroup,
  2544.                   pColumnLineData))
  2545.                   {
  2546.                   ErrCode = ERR_EXPORT_FILE ;
  2547.                   goto Exit0 ;
  2548.                   }
  2549.                }
  2550.             }  // for Counter...
  2551.  
  2552.          // done with the object, done with the buffer
  2553.          if (pColumnLineData)
  2554.             {
  2555.             MemoryFree (pColumnLineData) ;
  2556.             ColumnTotal = 0 ;
  2557.             pColumnLineData = NULL ;
  2558.             }
  2559.          }  // for Object
  2560.  
  2561.  
  2562.       }  // for System...
  2563.  
  2564. Exit0:
  2565.  
  2566.    SetArrowCursor() ;
  2567.  
  2568.    if (pColumnLineData)
  2569.       {
  2570.       MemoryFree (pColumnLineData) ;
  2571.       }
  2572.  
  2573.    if (hFile)
  2574.       {
  2575.       CloseHandle (hFile) ;
  2576.       }
  2577.  
  2578.    if (pFileName)
  2579.       {
  2580.       if (ErrCode)
  2581.          {
  2582.          DlgErrorBox (hWndGraph, ErrCode, pFileName) ;
  2583.          }
  2584.  
  2585.       MemoryFree (pFileName) ;
  2586.       }
  2587.  
  2588. }  // ExportReport
  2589.  
  2590.  
  2591. BOOL
  2592. BuildNewValueListForReport (
  2593. )
  2594. {
  2595.     PREPORT pReport;
  2596.  
  2597.     pReport = ReportData (hWndReport);
  2598.     
  2599.     return BuildValueListForSystems (
  2600.         pReport->pSystemFirst,
  2601.         pReport->pLineFirst);
  2602.  
  2603. }
  2604.  
  2605.  
  2606. 
  2607.